summaryrefslogtreecommitdiff
path: root/arch/s390/pci/pci_event.c
diff options
context:
space:
mode:
authorNiklas Schnelle <schnelle@linux.ibm.com>2024-11-25 10:35:10 +0100
committerHeiko Carstens <hca@linux.ibm.com>2024-11-28 14:12:04 +0100
commit48796104c864cf4dafa80bd8c2ce88f9c92a65ea (patch)
tree303a1bddcf9d5601b19f477d37d7fa7085742d2e /arch/s390/pci/pci_event.c
parentadb44a4bfc8a3312d2a13cc09d2b89d5828e7702 (diff)
downloadlwn-48796104c864cf4dafa80bd8c2ce88f9c92a65ea.tar.gz
lwn-48796104c864cf4dafa80bd8c2ce88f9c92a65ea.zip
s390/pci: Fix leak of struct zpci_dev when zpci_add_device() fails
Prior to commit 0467cdde8c43 ("s390/pci: Sort PCI functions prior to creating virtual busses") the IOMMU was initialized and the device was registered as part of zpci_create_device() with the struct zpci_dev freed if either resulted in an error. With that commit this was moved into a separate function called zpci_add_device(). While this new function logs when adding failed, it expects the caller not to use and to free the struct zpci_dev on error. This difference between it and zpci_create_device() was missed while changing the callers and the incompletely initialized struct zpci_dev may get used in zpci_scan_configured_device in the error path. This then leads to a crash due to the device not being registered with the zbus. It was also not freed in this case. Fix this by handling the error return of zpci_add_device(). Since in this case the zdev was not added to the zpci_list it can simply be discarded and freed. Also make this more explicit by moving the kref_init() into zpci_add_device() and document that zpci_zdev_get()/zpci_zdev_put() must be used after adding. Cc: stable@vger.kernel.org Fixes: 0467cdde8c43 ("s390/pci: Sort PCI functions prior to creating virtual busses") Reviewed-by: Gerd Bayer <gbayer@linux.ibm.com> Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com> Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Diffstat (limited to 'arch/s390/pci/pci_event.c')
-rw-r--r--arch/s390/pci/pci_event.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
index 47f934f4e828..7f7b732b3f3e 100644
--- a/arch/s390/pci/pci_event.c
+++ b/arch/s390/pci/pci_event.c
@@ -340,7 +340,10 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_CONFIGURED);
if (IS_ERR(zdev))
break;
- zpci_add_device(zdev);
+ if (zpci_add_device(zdev)) {
+ kfree(zdev);
+ break;
+ }
} else {
/* the configuration request may be stale */
if (zdev->state != ZPCI_FN_STATE_STANDBY)
@@ -354,7 +357,10 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_STANDBY);
if (IS_ERR(zdev))
break;
- zpci_add_device(zdev);
+ if (zpci_add_device(zdev)) {
+ kfree(zdev);
+ break;
+ }
} else {
zpci_update_fh(zdev, ccdf->fh);
}