]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
efi_loader: avoid pointer access after calling efi_delete_handle
authorMasahisa Kojima <masahisa.kojima@linaro.org>
Fri, 19 Jan 2024 00:45:44 +0000 (09:45 +0900)
committerHeinrich Schuchardt <heinrich.schuchardt@canonical.com>
Sun, 21 Jan 2024 10:24:24 +0000 (11:24 +0100)
efi_delete_handle() calls efi_purge_handle(), then it finally
frees the EFI handle.
Both diskobj and handle variables in efi_disk_remove() have
the same pointer, we can not access diskobj->dp after calling
efi_delete_handle().

This commit saves the struct efi_device_path pointer before
calling efi_delete_handle(). This commit also fixes the
missing free for volume member in struct efi_disk_obj.

This commit also removes the container_of() calls, and
adds the TODO comment of missing efi_close_protocol() call
for the parent EFI_BLOCK_IO_PROTOCOL.

Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
lib/efi_loader/efi_disk.c

index 013842f077668c2e9744bb1c7ee5631e8fb7a91e..105f0801252a9f337dbd0fbab0c8947abae2277b 100644 (file)
@@ -707,7 +707,9 @@ int efi_disk_remove(void *ctx, struct event *event)
        struct udevice *dev = event->data.dm.dev;
        efi_handle_t handle;
        struct blk_desc *desc;
+       struct efi_device_path *dp = NULL;
        struct efi_disk_obj *diskobj = NULL;
+       struct efi_simple_file_system_protocol *volume = NULL;
        efi_status_t ret;
 
        if (dev_tag_get_ptr(dev, DM_TAG_EFI, (void **)&handle))
@@ -718,24 +720,30 @@ int efi_disk_remove(void *ctx, struct event *event)
        case UCLASS_BLK:
                desc = dev_get_uclass_plat(dev);
                if (desc && desc->uclass_id != UCLASS_EFI_LOADER)
-                       diskobj = container_of(handle, struct efi_disk_obj,
-                                              header);
+                       diskobj = (struct efi_disk_obj *)handle;
                break;
        case UCLASS_PARTITION:
-               diskobj = container_of(handle, struct efi_disk_obj, header);
+               diskobj = (struct efi_disk_obj *)handle;
+
+               /* TODO: closing the parent EFI_BLOCK_IO_PROTOCOL is missing. */
+
                break;
        default:
                return 0;
        }
 
+       if (diskobj) {
+               dp = diskobj->dp;
+               volume = diskobj->volume;
+       }
+
        ret = efi_delete_handle(handle);
        /* Do not delete DM device if there are still EFI drivers attached. */
        if (ret != EFI_SUCCESS)
                return -1;
 
-       if (diskobj)
-               efi_free_pool(diskobj->dp);
-
+       efi_free_pool(dp);
+       free(volume);
        dev_tag_del(dev, DM_TAG_EFI);
 
        return 0;