[PATCH v2 1/3] efi_loader: avoid pointer access after calling efi_delete_handle

Ilias Apalodimas ilias.apalodimas at linaro.org
Wed Jan 17 12:51:35 CET 2024


Hi Kojima-san

On Wed, 17 Jan 2024 at 11:46, Masahisa Kojima
<masahisa.kojima at linaro.org> wrote:
>
> 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 at linaro.org>
> ---
>  lib/efi_loader/efi_disk.c | 23 +++++++++++++++++------
>  1 file changed, 17 insertions(+), 6 deletions(-)
>
> diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
> index 013842f077..ce46c1092a 100644
> --- a/lib/efi_loader/efi_disk.c
> +++ b/lib/efi_loader/efi_disk.c
> @@ -707,35 +707,46 @@ 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))
>                 return 0;
>
> +       if (!handle)
> +               return 0;
> +

Is there a chance dev_tag_get_ptr() will return a NULL handle?

>         id = device_get_uclass_id(dev);
>         switch (id) {
>         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);

Hmm, in which context are the dp and volume pointers allocated? The
handle is now freed, can we reliably access dp and volume ptrs?

>         /* 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;
> --
> 2.34.1
>

Thanks
/Ilias


More information about the U-Boot mailing list