Re: [PATCH 2/3] efi_loader: avoid pointer access after calling efi_delete_handle

Heinrich Schuchardt xypron.glpk at gmx.de
Tue Dec 26 02:43:09 CET 2023



Am 26. Dezember 2023 02:13:08 MEZ schrieb Masahisa Kojima <masahisa.kojima at linaro.org>:
>Hi Heinrich,
>
>On Mon, 25 Dec 2023 at 19:05, Heinrich Schuchardt <xypron.glpk at gmx.de> wrote:
>>
>> On 12/25/23 05:43, Masahisa Kojima 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.
>> >
>> > Signed-off-by: Masahisa Kojima <masahisa.kojima at linaro.org>
>> > ---
>> >   lib/efi_loader/efi_disk.c | 12 +++++++++---
>> >   1 file changed, 9 insertions(+), 3 deletions(-)
>> >
>> > diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
>> > index a2f8b531a3..415d8601ba 100644
>> > --- a/lib/efi_loader/efi_disk.c
>> > +++ b/lib/efi_loader/efi_disk.c
>> > @@ -701,7 +701,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))
>> > @@ -722,14 +724,18 @@ int efi_disk_remove(void *ctx, struct event *event)
>> >               return 0;
>> >       }
>> >
>> > +     if (diskobj) {
>>
>>
>>    diskobj = container_of(handle, struct efi_disk_obj, header);
>>
>> can be replaced by
>>
>>    diskobj = handle
>>
>> We should check the handle immediately after dev_tag_get_ptr() and
>> return 0 if the handle == NULL.
>
>OK, I will try to improve the efi_disk_remove() function.
>
>>
>> > +             dp = diskobj->dp;
>> > +             volume = diskobj->volume;
>> > +     }
>> > +
>> >       ret = efi_delete_handle(handle);
>>
>> We must not delete the handle in case of UCLASS_EFI_LOADER.
>>
>> Instead of calling efi_delete_handle we should uninstall all protocols
>> that we have installed. If no protocol is left the handle will go away.
>>
>> To make the protocols to delete tractable they should be opened with
>> BY_DRIVER.
>
>efi_delete_handle() calls efi_remove_all_protocols(), and frees the efi handle
>if no protocol is left on the handle.
>So I think efi_delete_handle() does all the required processes mentioned above.

Given an EFI application like iPXE that provides a handle with the block IO protocol implemented by the application: Why should U-Boot remove the block IO protocol or the device path protocol when the application calls DisconnectController()?

Best regards

Heinrich

>
>>
>> When a partition is removed we must close the protocol interfaces opened
>> with EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER (cf. efi_disk_add_dev()).
>
>OK, I will fix this.
>
>Thanks,
>Masahisa Kojima
>
>>
>> Best regards
>>
>> Heinrich
>>
>> >       /* 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;
>>


More information about the U-Boot mailing list