From: Anthony Krowiak <akrowiak@linux.ibm.com>
To: sashiko-reviews@lists.linux.dev
Cc: Alexander Gordeev <agordeev@linux.ibm.com>,
Heiko Carstens <hca@linux.ibm.com>,
Vasily Gorbik <gor@linux.ibm.com>,
kvm@vger.kernel.org, linux-s390@vger.kernel.org,
Christian Borntraeger <borntraeger@linux.ibm.com>,
Matthew Rosato <mjrosato@linux.ibm.com>,
Jason Herne <jjherne@linux.ibm.com>
Subject: Re: [PATCH v8 5/6] s390/vfio-ap: fix queue state leakage to guest and host
Date: Tue, 29 Sep 2026 07:41:33 -0400 [thread overview]
Message-ID: <e4807f54-f443-49df-b6cb-e77d4986dcd9@linux.ibm.com> (raw)
In-Reply-To: <20260925130308.D988B1F000FF@smtp.kernel.org>
On 9/25/26 9:03 AM, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
> - [High] crypto: vfio: Use-After-Free of vfio_ap_queue in vfio_ap_on_qstate_transition
> - [High] crypto: vfio: TOCTOU on q->matrix_mdev leads to unprotected KVM state updates and deadlocks
> - [Low] crypto: vfio: Incorrect comment for __drv_notify_qstate_transitioned
> --
>
> commit 6964322bafaab43ec603a04a262b5d1370b6779d
> Author: Anthony Krowiak <akrowiak@linux.ibm.com>
>
> s390/vfio-ap: fix queue state leakage to guest and host
>
> This patch limits the wait for a queue reset to complete and prevents the
> leakage of queue state to a guest. It introduces an on_qstate_transition
> callback to track queue state changes and restricts queue passability to
> fully zeroized states.
>
> Cc: stable@vger.kernel.org
>
>> diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
>> index d82df5b4e2db3..a53cfad3543eb 100644
>> --- a/drivers/s390/crypto/ap_bus.c
>> +++ b/drivers/s390/crypto/ap_bus.c
> [ ... ]
>> @@ -1979,6 +1979,28 @@ static inline void notify_scan_complete(void)
>> __drv_notify_scan_complete);
>> }
>>
>> +/* Helper function for notify_config_changed */
>> +static int __drv_notify_qstate_transitioned(struct device_driver *drv, void *data)
> [Severity: Low]
> Is this comment accurate? It states this is a helper function for
> notify_config_changed, but the function name and usage indicate it is a
> helper for notify_qstate_transitioned.
This will be fixed ion the forthcoming v9 patch series
>
>> +{
> [ ... ]
>> diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
>> index ffc2d8715bd96..cd4a436c43194 100644
>> --- a/drivers/s390/crypto/vfio_ap_ops.c
>> +++ b/drivers/s390/crypto/vfio_ap_ops.c
> [ ... ]
>> @@ -3309,3 +3310,46 @@ void vfio_ap_on_scan_complete(struct ap_config_info *new_config_info,
>>
>> mutex_unlock(&matrix_dev->guests_lock);
>> }
>> +
>> +/**
>> + * vfio_ap_on_qstate_transition:
>> + *Instead of calling vfio_ap_find_queue() without locks and reading q->matrix_mdev, vfio_ap_on_qstate_transition() now calls get_update_locks_by_apqn(apqn)
>> + * AP bus callback notifying the vfio_ap device driver that the state of a
>> + * queue has transitioned.
>> + *
>> + * @qstate_trans: the object containing a reference to the queue device and the
>> + * state to which it transitioned.
>> + */
>> +void vfio_ap_on_qstate_transition(struct ap_qstate_transition *qstate_trans)
>> +{
>> + struct vfio_ap_queue *q = vfio_ap_find_queue(qstate_trans->queue->qid);
>> + DECLARE_BITMAP(apm_filtered, AP_DEVICES);
>> +
>> + /*
>> + * If the queue is not bound to the vfio_ap device driver, then it won't
>> + * be passed through to a guest; so, no need to continue.
>> + */
>> + if (!q)
>> + return;
>> +
>> + get_update_locks_for_mdev(q->matrix_mdev);
> [Severity: High]
> Can this dereference a freed pointer?
>
> If vfio_ap_find_queue() reads the device's drvdata and drops the device
> reference before returning, q has no reference count. Because
> vfio_ap_on_qstate_transition() holds no locks, a concurrent sysfs unbind
> can invoke vfio_ap_mdev_remove_queue(), which clears drvdata and calls
> kfree(q).
>
> This would cause a use-after-free when reading q->matrix_mdev.
>
> Additionally, is there a TOCTOU race when reading q->matrix_mdev without
> locks?
>
> If q->matrix_mdev is NULL here, get_update_locks_for_mdev() will skip
> acquiring kvm->lock. If another thread concurrently updates q->matrix_mdev
> to a non-NULL value while waiting on guests_lock, this could lead to issues
> later in the function.
This is a legitimate concern.
Instead of calling vfio_ap_find_queue() without locks and reading
q->matrix_mdev,
matrix_mdev = get_update_locks_by_apqn(apqn) can be used since the apqn
can be
obtained from qstate_trans->queue->qid. get_update_locks_by_apqn()
acquires matrix_dev->guests_lock, searches matrix_dev->mdev_list for the
mdev that owns the apqn, acquires matrix_mdev->kvm->lock (if attached to
a guest), and finally acquires matrix_dev->mdevs_lock. Lookup of q via
vfio_ap_mdev_get_queue() is done entirely under the protection of all
three locks, completely eliminating the UAF and TOCTOU races.
>
>> +
>> + switch (qstate_trans->new_state) {
>> + case AP_QUEUE_CONFIG_ON:
>> + case AP_QUEUE_CHKSTOP_OFF:
>> + vfio_ap_mdev_reset_queue(q);
>> + flush_work(&q->reset_work);
> [Severity: High]
> Does this also cause a use-after-free for the same reason? Passing the
> potentially freed queue object to vfio_ap_mdev_reset_queue(q) and flushing
> its work struct could trigger further memory corruption.
As stated above, using matrix_mdev = get_update_locks_by_apqn(apqn) should
also resolve this issue. If q is retrieved from matrix_mdev under
mdevs_lock, and vfio_ap_mdev_remove_queue() requires mdevs_lock to unlink
and free q, q is guaranteed valid throughout the reset and
flush_work(&q->reset_work) sequence.
>
>> +
>> + if (q->matrix_mdev) {
>> + if (vfio_ap_mdev_filter_matrix(q->matrix_mdev, apm_filtered)) {
>> + vfio_ap_mdev_update_guest_apcb(q->matrix_mdev);
> [Severity: High]
> If q->matrix_mdev changed concurrently after get_update_locks_for_mdev()
> was called, could this update the KVM guest state without having acquired
> the proper KVM locks?
As stated above, using matrix_mdev = get_update_locks_by_apqn(apqn) should
also resolve this issue. If an mdev is attached to a guest
(matrix_mdev->kvm != NULL), kvm->lock is held. All matrix filtering,
APCB updates (vfio_ap_mdev_update_guest_apcb()), and queue resets operate
strictly on the locked matrix_mdev handle, with no unprotected pointer
re-reads.
>
>> + reset_queues_for_apids(q->matrix_mdev, apm_filtered);
>> + }
>> + }
>> + break;
>> + default:
>> + break;
>> + }
>> +Instead of calling vfio_ap_find_queue() without locks and reading q->matrix_mdev, vfio_ap_on_qstate_transition() now calls get_update_locks_by_apqn(apqn)
>> + release_update_locks_for_mdev(q->matrix_mdev);
> [Severity: High]
> If q->matrix_mdev was modified between the initial acquisition and here,
> would this call mutex_unlock() on a lock it did not acquire, or leave
> an acquired lock perpetually locked?
As stated above, using matrix_mdev = get_update_locks_by_apqn(apqn) should
also resolve this issue. At the exit point, the locks can be freed with
release_update_locks_for_mdev(matrix_mdev), passing the exact same
matrix_mdev that was locked by get_update_locks_by_apqn(). This guarantees
100% symmetry between lock acquisition and release under all execution
paths.
>
>> +}
next prev parent reply other threads:[~2026-09-29 11:41 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-25 12:45 [PATCH v8 0/6] s390/vfio-ap: Fix pre-existing bugs in vfio_ap device driver Anthony Krowiak
2026-09-25 12:45 ` [PATCH v8 1/6] s390/vfio-ap: Fix leaks of pinned NIB and registered GISC Anthony Krowiak
2026-09-25 12:57 ` sashiko-bot
2026-09-29 9:36 ` Anthony Krowiak
2026-09-25 12:45 ` [PATCH v8 2/6] s390/vfio-ap: Fix failure to release IRQ notification eventfd contexts Anthony Krowiak
2026-09-25 12:53 ` sashiko-bot
2026-09-25 12:45 ` [PATCH v8 3/6] s390/vfio-ap: Fix unbounded loop in apq_reset_check() Anthony Krowiak
2026-09-25 13:00 ` sashiko-bot
2026-09-29 11:11 ` Anthony Krowiak
2026-09-25 12:45 ` [PATCH v8 4/6] s390/vfio-ap: Use AP_DOMAINS for adm_add bitmap size in vfio_ap_mdev_cfg_add() Anthony Krowiak
2026-09-25 12:51 ` sashiko-bot
2026-09-25 12:45 ` [PATCH v8 5/6] s390/vfio-ap: fix queue state leakage to guest and host Anthony Krowiak
2026-09-25 13:03 ` sashiko-bot
2026-09-29 11:41 ` Anthony Krowiak [this message]
2026-09-25 12:45 ` [PATCH v8 6/6] s390/vfio-ap: replace guest-reachable WARNs with ratelimited warnings Anthony Krowiak
2026-09-25 12:59 ` sashiko-bot
2026-09-25 15:55 ` Anthony Krowiak
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=e4807f54-f443-49df-b6cb-e77d4986dcd9@linux.ibm.com \
--to=akrowiak@linux.ibm.com \
--cc=agordeev@linux.ibm.com \
--cc=borntraeger@linux.ibm.com \
--cc=gor@linux.ibm.com \
--cc=hca@linux.ibm.com \
--cc=jjherne@linux.ibm.com \
--cc=kvm@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=mjrosato@linux.ibm.com \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox