> From: Alex Williamson <alex.william...@redhat.com> > Sent: Wednesday, September 21, 2022 3:17 AM > > On Fri, 9 Sep 2022 18:22:38 +0800 > Kevin Tian <kevin.t...@intel.com> wrote: > > > From: Yi Liu <yi.l....@intel.com> > > > > and manage available ports inside @init/@release. > > > > Signed-off-by: Yi Liu <yi.l....@intel.com> > > Signed-off-by: Kevin Tian <kevin.t...@intel.com> > > Reviewed-by: Jason Gunthorpe <j...@nvidia.com> > > --- > > samples/vfio-mdev/mtty.c | 67 +++++++++++++++++++++++----------------- > > 1 file changed, 39 insertions(+), 28 deletions(-) > > > > diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c > > index f42a59ed2e3f..41301d50b247 100644 > > --- a/samples/vfio-mdev/mtty.c > > +++ b/samples/vfio-mdev/mtty.c > ... > > +static int mtty_probe(struct mdev_device *mdev) > > +{ > > + struct mdev_state *mdev_state; > > + int ret; > > + > > + mdev_state = vfio_alloc_device(mdev_state, vdev, &mdev->dev, > > + &mtty_dev_ops); > > + if (IS_ERR(mdev_state)) > > + return PTR_ERR(mdev_state); > > > > ret = vfio_register_emulated_iommu_dev(&mdev_state->vdev); > > if (ret) > > - goto err_vconfig; > > + goto err_put_vdev; > > dev_set_drvdata(&mdev->dev, mdev_state); > > return 0; > > > > -err_vconfig: > > - kfree(mdev_state->vconfig); > > -err_state: > > - vfio_uninit_group_dev(&mdev_state->vdev); > > - kfree(mdev_state); > > -err_nr_ports: > > - atomic_add(nr_ports, &mdev_avail_ports); > > +err_put_vdev: > > + vfio_put_device(&mdev_state->vdev); > > return ret; > > } > > > > +static void mtty_release_dev(struct vfio_device *vdev) > > +{ > > + struct mdev_state *mdev_state = > > + container_of(vdev, struct mdev_state, vdev); > > + > > + kfree(mdev_state->vconfig); > > + vfio_free_device(vdev); > > + atomic_add(mdev_state->nr_ports, &mdev_avail_ports); > > I must be missing something, isn't this a use-after-free?
Yes, it's a use-after-free indeed. Thanks for catching it! > > mdev_state is allocated via vfio_alloc_device(), where vdev is the > first entry in that structure, so this is equivalent to > kvfree(mdev_state). mbochs has the same issue. mdpy and vfio-ap > adjust global counters after vfio_free_device(), which I think muddies > the situation. Shouldn't we look suspiciously at any .release callback > where vfio_free_device() isn't the last thing executed? Thanks, > Yes. I'll scrutinize it again. To be consistent I'll make sure the free is the last line in all .release callbacks though not required for some (e.g. mdpy and vfio-ap).