]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
pds_core: fix auxiliary device add/del races
authorNikhil P. Rao <nikhil.rao@amd.com>
Tue, 14 Jul 2026 21:07:45 +0000 (21:07 +0000)
committerJakub Kicinski <kuba@kernel.org>
Tue, 21 Jul 2026 19:46:43 +0000 (12:46 -0700)
Two paths add or delete the same slot (pf->vfs[vf_id].padev): a VF's
pdsc_reset_done() and the PF's devlink enable_vnet/disable_vnet handler.
They serialize on config_lock, but neither guards the slot under it
correctly.

add() registers and stores a new auxiliary device without first checking
the slot, so a second add of an already-populated slot leaks the first
device. del() makes that check outside config_lock, so two concurrent
dels can both pass it; the first clears the slot, and the second
dereferences a NULL pointer.

Check and update the slot under config_lock in both paths.

Fixes: b699bdc720c0 ("pds_core: specify auxiliary_device to be created")
Reported-by: sashiko-bot@kernel.org # Running on a local machine
Signed-off-by: Nikhil P. Rao <nikhil.rao@amd.com>
Reviewed-by: Brett Creeley <brett.creeley@amd.com>
Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
Link: https://patch.msgid.link/20260714210745.1785625-1-nikhil.rao@amd.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/amd/pds_core/auxbus.c

index 73b3481220b1acb8b5aa018c6cedb36fb5de5c02..3acafe10a6d5baa0dded69956d9397ae7fea3c87 100644 (file)
@@ -177,17 +177,21 @@ void pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf,
 {
        struct pds_auxiliary_dev *padev;
 
-       if (!*pd_ptr)
-               return;
-
        mutex_lock(&pf->config_lock);
 
+       /* A concurrent del may have already torn this device down and
+        * cleared it.
+        */
        padev = *pd_ptr;
+       if (!padev)
+               goto out_unlock;
+
        pds_client_unregister(pf, padev->client_id);
        auxiliary_device_delete(&padev->aux_dev);
        auxiliary_device_uninit(&padev->aux_dev);
        *pd_ptr = NULL;
 
+out_unlock:
        mutex_unlock(&pf->config_lock);
 }
 
@@ -210,6 +214,13 @@ int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf,
 
        mutex_lock(&pf->config_lock);
 
+       /* Nothing to do if the aux device is already present.  This also
+        * guards against a second add overwriting *pd_ptr and leaking the
+        * first, symmetric with the check in pdsc_auxbus_dev_del().
+        */
+       if (*pd_ptr)
+               goto out_unlock;
+
        mask = BIT_ULL(PDSC_S_FW_DEAD) |
               BIT_ULL(PDSC_S_STOPPING_DRIVER);
        if (cf->state & mask) {