| From 8c4ad73abf8516648028b31c22dd28de97ec3ca0 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 14 Feb 2025 13:01:37 +0100 |
| Subject: s390/ism: add release function for struct device |
| |
| From: Julian Ruess <julianr@linux.ibm.com> |
| |
| [ Upstream commit 915e34d5ad35a6a9e56113f852ade4a730fb88f0 ] |
| |
| According to device_release() in /drivers/base/core.c, |
| a device without a release function is a broken device |
| and must be fixed. |
| |
| The current code directly frees the device after calling device_add() |
| without waiting for other kernel parts to release their references. |
| Thus, a reference could still be held to a struct device, |
| e.g., by sysfs, leading to potential use-after-free |
| issues if a proper release function is not set. |
| |
| Fixes: 8c81ba20349d ("net/smc: De-tangle ism and smc device initialization") |
| Reviewed-by: Alexandra Winter <wintera@linux.ibm.com> |
| Reviewed-by: Wenjia Zhang <wenjia@linux.ibm.com> |
| Signed-off-by: Julian Ruess <julianr@linux.ibm.com> |
| Signed-off-by: Alexandra Winter <wintera@linux.ibm.com> |
| Reviewed-by: Simon Horman <horms@kernel.org> |
| Link: https://patch.msgid.link/20250214120137.563409-1-wintera@linux.ibm.com |
| Signed-off-by: Jakub Kicinski <kuba@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/s390/net/ism_drv.c | 14 ++++++++++++-- |
| 1 file changed, 12 insertions(+), 2 deletions(-) |
| |
| diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c |
| index e36e3ea165d3b..2f34761e64135 100644 |
| --- a/drivers/s390/net/ism_drv.c |
| +++ b/drivers/s390/net/ism_drv.c |
| @@ -588,6 +588,15 @@ static int ism_dev_init(struct ism_dev *ism) |
| return ret; |
| } |
| |
| +static void ism_dev_release(struct device *dev) |
| +{ |
| + struct ism_dev *ism; |
| + |
| + ism = container_of(dev, struct ism_dev, dev); |
| + |
| + kfree(ism); |
| +} |
| + |
| static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| { |
| struct ism_dev *ism; |
| @@ -601,6 +610,7 @@ static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| dev_set_drvdata(&pdev->dev, ism); |
| ism->pdev = pdev; |
| ism->dev.parent = &pdev->dev; |
| + ism->dev.release = ism_dev_release; |
| device_initialize(&ism->dev); |
| dev_set_name(&ism->dev, dev_name(&pdev->dev)); |
| ret = device_add(&ism->dev); |
| @@ -637,7 +647,7 @@ static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| device_del(&ism->dev); |
| err_dev: |
| dev_set_drvdata(&pdev->dev, NULL); |
| - kfree(ism); |
| + put_device(&ism->dev); |
| |
| return ret; |
| } |
| @@ -682,7 +692,7 @@ static void ism_remove(struct pci_dev *pdev) |
| pci_disable_device(pdev); |
| device_del(&ism->dev); |
| dev_set_drvdata(&pdev->dev, NULL); |
| - kfree(ism); |
| + put_device(&ism->dev); |
| } |
| |
| static struct pci_driver ism_driver = { |
| -- |
| 2.39.5 |
| |