[PATCH v2 1/3] efi_loader: avoid pointer access after calling efi_delete_handle
Ilias Apalodimas
ilias.apalodimas at linaro.org
Thu Jan 18 07:13:43 CET 2024
On Thu, 18 Jan 2024 at 02:16, Masahisa Kojima
<masahisa.kojima at linaro.org> wrote:
>
> On Wed, 17 Jan 2024 at 20:52, Ilias Apalodimas
> <ilias.apalodimas at linaro.org> wrote:
> >
> > 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?
>
> There is no chance unless we actually set a NULL.
> Checking the return value of dev_tag_get_ptr above is enough, I will
> remove this.
>
> >
> > > 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?
>
> dp and volume are allocated in efi_disk_add_dev() when the block
> device is probed.
> efi_delete_handle() will remove all protocols from the handle,
> efi_uninstall_protocol()
> checks whether protocol_interface is actually installed. So dp and
> volume should be
> freed after efi_delete_handle().
Ok that makes sense,
With the check above removed
Reviewed-by: Ilias Apalodimas <ilias.apalodimas at linaro.org>
>
> Thanks,
> Masahisa Kojima
>
> >
> > > /* 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