Re: [PATCH 2/4] s390/vfio-ap: Fix failure to release IRQ notification eventfd contexts

Matthew Rosato <[email protected]>
Newsgroups org.kernel.vger.stable,org.kernel.vger.kvm,org.kernel.vger.linux-kernel,org.kernel.vger.linux-s390
Message-ID <[email protected]>
On 8/24/26 9:58 AM, Anthony Krowiak wrote:
> When userspace registers IRQ notification eventfds via the
> VFIO_DEVICE_SET_IRQS ioctl, vfio_ap_set_request_irq() and
> vfio_ap_set_cfg_change_irq() each call eventfd_ctx_fdget(), which
> takes a reference on the eventfd_ctx and stores it in
> matrix_mdev->req_trigger and matrix_mdev->cfg_chg_trigger
> respectively.
> 
> These references are dropped only when userspace explicitly replaces
> or clears them via a subsequent SET_IRQS call.  If the device is
> closed without that explicit teardown - because the guest exits,
> the VM process crashes, or the device file is simply closed -
> neither vfio_ap_mdev_close_device() nor the remove path releases
> these references.  The eventfd_ctx backing objects and their
> associated file references therefore leak for the lifetime of the
> kernel.
> 
> Fix this by introducing vfio_ap_mdev_release_eventfds() and calling
> it from vfio_ap_mdev_close_device() after vfio_ap_mdev_unset_kvm().
> The VFIO core guarantees that close_device is called before
> vfio_unregister_group_dev() returns in the remove path, so fixing
> close_device is sufficient to cover both teardown paths.
> 
> Note:
> ~~~~
> The matrix_dev->mdevs lock must be held during the call to
> vfio_ap_mdev_release_eventfds(). There is a small window between the calls
> to vfio_ap_mdev_unset_kvm() which gets and releases the update locks
> and the acquisition of the matrix_dev->mdevs_lock mutex during which
> it is possible - although highly unlikely during normal operation - whereby
> a concurrent SET_IRQS call can get in.
> 
> Taking matrix_dev->mdevs_lock around vfio_ap_mdev_release_eventfds()
> is sufficient to make this race-free. The SET_IRQS ioctl path writes
> req_trigger and cfg_chg_trigger only from vfio_ap_mdev_ioctl(), which
> holds mdevs_lock for its entire duration and always calls
> eventfd_ctx_put() on the previous value before storing the new one.
> 
> Any number of concurrent SET_IRQS calls during the window between
> vfio_ap_mdev_unset_kvm() and the acquisition of mdevs_lock are
> therefore safe: each ioctl invocation puts the reference it found and
> installs a new one, leaving exactly one live reference in the field
> when it releases the lock. When release_eventfds subsequently acquires
> mdevs_lock it finds that single surviving reference and puts it.
> Conversely, a SET_IRQS call that loses the race and blocks on
> mdevs_lock will find the field NULL after release_eventfds finishes,
> take ownership of the reference it just created, and install it into a
> field that will never be read again - a transient leak. To close that
> final case, callers must ensure no new SET_IRQS ioctls can be issued
> after close_device() is called, which the VFIO core guarantees by
> releasing the device file before invoking close_device().
> 
> Fixes: bf48961f6f48e ("s390/vfio-ap: realize the VFIO_DEVICE_SET_IRQS ioctl")
> Cc: [email protected]
> Signed-off-by: Anthony Krowiak <[email protected]>

Reviewed-by: Matthew Rosato <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.