Lee Duncan 96a494
From: Yang Yingliang <yangyingliang@huawei.com>
Lee Duncan 96a494
Date: Sat, 12 Nov 2022 17:43:10 +0800
Lee Duncan 96a494
Subject: scsi: fcoe: Fix possible name leak when device_register() fails
Lee Duncan 96a494
Git-commit: 47b6a122c7b69a876c7ee2fc064a26b09627de9d
Lee Duncan 96a494
Patch-mainline: v6.1 or v6.1-rc9 (next release)
Lee Duncan 96a494
References: git-fixes
Lee Duncan 96a494
Lee Duncan 96a494
If device_register() returns an error, the name allocated by dev_set_name()
Lee Duncan 96a494
needs to be freed. As the comment of device_register() says, one should use
Lee Duncan 96a494
put_device() to give up the reference in the error path. Fix this by
Lee Duncan 96a494
calling put_device(), then the name can be freed in kobject_cleanup().
Lee Duncan 96a494
Lee Duncan 96a494
The 'fcf' is freed in fcoe_fcf_device_release(), so the kfree() in the
Lee Duncan 96a494
error path can be removed.
Lee Duncan 96a494
Lee Duncan 96a494
The 'ctlr' is freed in fcoe_ctlr_device_release(), so don't use the error
Lee Duncan 96a494
label, just return NULL after calling put_device().
Lee Duncan 96a494
Lee Duncan 96a494
Fixes: 9a74e884ee71 ("[SCSI] libfcoe: Add fcoe_sysfs")
Lee Duncan 96a494
Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
Lee Duncan 96a494
Link: https://lore.kernel.org/r/20221112094310.3633291-1-yangyingliang@huawei.com
Lee Duncan 96a494
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Lee Duncan 96a494
Acked-by: Lee Duncan <lduncan@suse.com>
Lee Duncan 96a494
---
Lee Duncan 96a494
 drivers/scsi/fcoe/fcoe_sysfs.c | 19 ++++++++++---------
Lee Duncan 96a494
 1 file changed, 10 insertions(+), 9 deletions(-)
Lee Duncan 96a494
Lee Duncan 96a494
diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c
Lee Duncan 96a494
index af658aa38fed..6260aa5ea6af 100644
Lee Duncan 96a494
--- a/drivers/scsi/fcoe/fcoe_sysfs.c
Lee Duncan 96a494
+++ b/drivers/scsi/fcoe/fcoe_sysfs.c
Lee Duncan 96a494
@@ -830,14 +830,15 @@ struct fcoe_ctlr_device *fcoe_ctlr_device_add(struct device *parent,
Lee Duncan 96a494
 
Lee Duncan 96a494
 	dev_set_name(&ctlr->dev, "ctlr_%d", ctlr->id);
Lee Duncan 96a494
 	error = device_register(&ctlr->dev);
Lee Duncan 96a494
-	if (error)
Lee Duncan 96a494
-		goto out_del_q2;
Lee Duncan 96a494
+	if (error) {
Lee Duncan 96a494
+		destroy_workqueue(ctlr->devloss_work_q);
Lee Duncan 96a494
+		destroy_workqueue(ctlr->work_q);
Lee Duncan 96a494
+		put_device(&ctlr->dev);
Lee Duncan 96a494
+		return NULL;
Lee Duncan 96a494
+	}
Lee Duncan 96a494
 
Lee Duncan 96a494
 	return ctlr;
Lee Duncan 96a494
 
Lee Duncan 96a494
-out_del_q2:
Lee Duncan 96a494
-	destroy_workqueue(ctlr->devloss_work_q);
Lee Duncan 96a494
-	ctlr->devloss_work_q = NULL;
Lee Duncan 96a494
 out_del_q:
Lee Duncan 96a494
 	destroy_workqueue(ctlr->work_q);
Lee Duncan 96a494
 	ctlr->work_q = NULL;
Lee Duncan 96a494
@@ -1036,16 +1037,16 @@ struct fcoe_fcf_device *fcoe_fcf_device_add(struct fcoe_ctlr_device *ctlr,
Lee Duncan 96a494
 	fcf->selected = new_fcf->selected;
Lee Duncan 96a494
 
Lee Duncan 96a494
 	error = device_register(&fcf->dev);
Lee Duncan 96a494
-	if (error)
Lee Duncan 96a494
-		goto out_del;
Lee Duncan 96a494
+	if (error) {
Lee Duncan 96a494
+		put_device(&fcf->dev);
Lee Duncan 96a494
+		goto out;
Lee Duncan 96a494
+	}
Lee Duncan 96a494
 
Lee Duncan 96a494
 	fcf->state = FCOE_FCF_STATE_CONNECTED;
Lee Duncan 96a494
 	list_add_tail(&fcf->peers, &ctlr->fcfs);
Lee Duncan 96a494
 
Lee Duncan 96a494
 	return fcf;
Lee Duncan 96a494
 
Lee Duncan 96a494
-out_del:
Lee Duncan 96a494
-	kfree(fcf);
Lee Duncan 96a494
 out:
Lee Duncan 96a494
 	return NULL;
Lee Duncan 96a494
 }
Lee Duncan 96a494