Re: [PATCH v2 3/3] scsi: core: Call blk_mq_free_tag_set() earlier

Ming Lei
2022-07-01T14:39:49Z

On Fri, Jul 01, 2022 at 07:07:13AM -0700, Bart Van Assche wrote:
> On 6/30/22 20:44, Ming Lei wrote:
> > On Thu, Jun 30, 2022 at 02:37:33PM -0700, Bart Van Assche wrote:
> > > There are two .exit_cmd_priv implementations. Both implementations use
> > > resources associated with the SCSI host. Make sure that these resources are
> >
> > Please document what the exact resources associated with this SCSI host is.
> >
> > We need the root cause.
> >
> > I understand it might be related with module unloading, since ib_srp may
> > be gone already, but not sure if it is the exact one in this report.
>
> It is not necessary to unload ib_srp to trigger this scenario.
> Hot-unplugging an RDMA adapter used by the ib_srp driver is sufficient.
> Hot-unplugging triggers a call of srp_remove_one(). srp_remove_one() itself
> and also its caller free resources used by srp_exit_cmd_priv(), e.g. struct
> ib_device.

OK, looks it isn't same with Changhui's report.

>
> > > still available when .exit_cmd_priv is called by moving the .exit_cmd_priv
> > > calls from scsi_host_dev_release() to scsi_forget_host(). Moving
> > > blk_mq_free_tag_set() from scsi_host_dev_release() to scsi_forget_host() is
> > > safe because scsi_forget_host() drains all the request queues that use the
> > > host tag set. This guarantees that no requests are in flight and also that
> > > no new requests will be allocated from the host tag set.
> > >
> > > This patch fixes the following use-after-free:
> > >
> > > ==================================================================
> > > BUG: KASAN: use-after-free in srp_exit_cmd_priv+0x27/0xd0 [ib_srp]
> > > Read of size 8 at addr ffff888100337000 by task multipathd/16727
> >
> > What is the 8bytes buffer which triggers UAF? what does srp_exit_cmd_priv+0x27
> > point to?
>
> I think that Li already answered this question.

OK, from Li's input, the UAF is on the following code:

struct srp_device *dev = target->srp_host->srp_dev;

So looks you meant target->srp_host is freed by srp_remove_one() before calling
srp_exit_cmd_priv?

Then when is srp_remove_one() triggered? And why is it called before
scsi_remove_host()? Sorry for the stupid question since I am not familiar with srp.

Thanks,
Ming