efi_loader: error handling in efi_load_image()

If a failure occurs when trying to load an image, it is insufficient
to free() the EFI object. We must remove it from the object list,
too. Otherwise a use after free will occur the next time we
iterate over the object list.

Furthermore errors in setting up the image should be handled.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
master
Heinrich Schuchardt 7 years ago committed by Alexander Graf
parent 678e03a00c
commit b9b17598f4
  1. 31
      lib/efi_loader/efi_boottime.c

@ -1308,6 +1308,7 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
{
struct efi_loaded_image *info;
struct efi_object *obj;
efi_status_t ret;
EFI_ENTRY("%d, %p, %p, %p, %ld, %p", boot_policy, parent_image,
file_path, source_buffer, source_size, image_handle);
@ -1317,41 +1318,39 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
if (!source_buffer) {
struct efi_device_path *dp, *fp;
efi_status_t ret;
ret = efi_load_image_from_path(file_path, &source_buffer);
if (ret != EFI_SUCCESS) {
free(info);
free(obj);
return EFI_EXIT(ret);
}
if (ret != EFI_SUCCESS)
goto failure;
/*
* split file_path which contains both the device and
* file parts:
*/
efi_dp_split_file_path(file_path, &dp, &fp);
efi_setup_loaded_image(info, obj, dp, fp);
ret = efi_setup_loaded_image(info, obj, dp, fp);
if (ret != EFI_SUCCESS)
goto failure;
} else {
/* In this case, file_path is the "device" path, ie.
* something like a HARDWARE_DEVICE:MEMORY_MAPPED
*/
efi_setup_loaded_image(info, obj, file_path, NULL);
ret = efi_setup_loaded_image(info, obj, file_path, NULL);
if (ret != EFI_SUCCESS)
goto failure;
}
info->reserved = efi_load_pe(source_buffer, info);
if (!info->reserved) {
free(info);
free(obj);
return EFI_EXIT(EFI_UNSUPPORTED);
ret = EFI_UNSUPPORTED;
goto failure;
}
info->system_table = &systab;
info->parent_handle = parent_image;
*image_handle = obj->handle;
return EFI_EXIT(EFI_SUCCESS);
failure:
free(info);
efi_delete_handle(obj);
return EFI_EXIT(ret);
}
/*

Loading…
Cancel
Save