scsi: fcoe: Fix possible name leak when device_register() fails
authorYang Yingliang <yangyingliang@huawei.com>
Sat, 12 Nov 2022 09:43:10 +0000 (17:43 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 31 Dec 2022 12:32:35 +0000 (13:32 +0100)
[ Upstream commit 47b6a122c7b69a876c7ee2fc064a26b09627de9d ]

If device_register() returns an error, the name allocated by dev_set_name()
needs to be freed. As the comment of device_register() says, one should use
put_device() to give up the reference in the error path. Fix this by
calling put_device(), then the name can be freed in kobject_cleanup().

The 'fcf' is freed in fcoe_fcf_device_release(), so the kfree() in the
error path can be removed.

The 'ctlr' is freed in fcoe_ctlr_device_release(), so don't use the error
label, just return NULL after calling put_device().

Fixes: 9a74e884ee71 ("[SCSI] libfcoe: Add fcoe_sysfs")
Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
Link: https://lore.kernel.org/r/20221112094310.3633291-1-yangyingliang@huawei.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/scsi/fcoe/fcoe_sysfs.c

index af658aa..6260aa5 100644 (file)
@@ -830,14 +830,15 @@ struct fcoe_ctlr_device *fcoe_ctlr_device_add(struct device *parent,
 
        dev_set_name(&ctlr->dev, "ctlr_%d", ctlr->id);
        error = device_register(&ctlr->dev);
-       if (error)
-               goto out_del_q2;
+       if (error) {
+               destroy_workqueue(ctlr->devloss_work_q);
+               destroy_workqueue(ctlr->work_q);
+               put_device(&ctlr->dev);
+               return NULL;
+       }
 
        return ctlr;
 
-out_del_q2:
-       destroy_workqueue(ctlr->devloss_work_q);
-       ctlr->devloss_work_q = NULL;
 out_del_q:
        destroy_workqueue(ctlr->work_q);
        ctlr->work_q = NULL;
@@ -1036,16 +1037,16 @@ struct fcoe_fcf_device *fcoe_fcf_device_add(struct fcoe_ctlr_device *ctlr,
        fcf->selected = new_fcf->selected;
 
        error = device_register(&fcf->dev);
-       if (error)
-               goto out_del;
+       if (error) {
+               put_device(&fcf->dev);
+               goto out;
+       }
 
        fcf->state = FCOE_FCF_STATE_CONNECTED;
        list_add_tail(&fcf->peers, &ctlr->fcfs);
 
        return fcf;
 
-out_del:
-       kfree(fcf);
 out:
        return NULL;
 }