Commit f014165f authored by Zhou Guanghui's avatar Zhou Guanghui Committed by Martin K. Petersen

scsi: iscsi: Fix possible memory leak when device_register() failed

If device_register() returns error, the name allocated by the
dev_set_name() need be freed. As described in the comment of
device_register(), we should use put_device() to give up the reference in
the error path.

Fix this by calling put_device(), the name will be freed in the
kobject_cleanup(), and this patch modified resources will be released by
calling the corresponding callback function in the device_release().
Signed-off-by: default avatarZhou Guanghui <zhouguanghui1@huawei.com>
Link: https://lore.kernel.org/r/20221110033729.1555-1-zhouguanghui1@huawei.comReviewed-by: default avatarMike Christie <michael.christie@oracle.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 0954256e
...@@ -231,7 +231,7 @@ iscsi_create_endpoint(int dd_size) ...@@ -231,7 +231,7 @@ iscsi_create_endpoint(int dd_size)
dev_set_name(&ep->dev, "ep-%d", id); dev_set_name(&ep->dev, "ep-%d", id);
err = device_register(&ep->dev); err = device_register(&ep->dev);
if (err) if (err)
goto free_id; goto put_dev;
err = sysfs_create_group(&ep->dev.kobj, &iscsi_endpoint_group); err = sysfs_create_group(&ep->dev.kobj, &iscsi_endpoint_group);
if (err) if (err)
...@@ -245,10 +245,12 @@ iscsi_create_endpoint(int dd_size) ...@@ -245,10 +245,12 @@ iscsi_create_endpoint(int dd_size)
device_unregister(&ep->dev); device_unregister(&ep->dev);
return NULL; return NULL;
free_id: put_dev:
mutex_lock(&iscsi_ep_idr_mutex); mutex_lock(&iscsi_ep_idr_mutex);
idr_remove(&iscsi_ep_idr, id); idr_remove(&iscsi_ep_idr, id);
mutex_unlock(&iscsi_ep_idr_mutex); mutex_unlock(&iscsi_ep_idr_mutex);
put_device(&ep->dev);
return NULL;
free_ep: free_ep:
kfree(ep); kfree(ep);
return NULL; return NULL;
...@@ -766,7 +768,7 @@ iscsi_create_iface(struct Scsi_Host *shost, struct iscsi_transport *transport, ...@@ -766,7 +768,7 @@ iscsi_create_iface(struct Scsi_Host *shost, struct iscsi_transport *transport,
err = device_register(&iface->dev); err = device_register(&iface->dev);
if (err) if (err)
goto free_iface; goto put_dev;
err = sysfs_create_group(&iface->dev.kobj, &iscsi_iface_group); err = sysfs_create_group(&iface->dev.kobj, &iscsi_iface_group);
if (err) if (err)
...@@ -780,9 +782,8 @@ iscsi_create_iface(struct Scsi_Host *shost, struct iscsi_transport *transport, ...@@ -780,9 +782,8 @@ iscsi_create_iface(struct Scsi_Host *shost, struct iscsi_transport *transport,
device_unregister(&iface->dev); device_unregister(&iface->dev);
return NULL; return NULL;
free_iface: put_dev:
put_device(iface->dev.parent); put_device(&iface->dev);
kfree(iface);
return NULL; return NULL;
} }
EXPORT_SYMBOL_GPL(iscsi_create_iface); EXPORT_SYMBOL_GPL(iscsi_create_iface);
...@@ -1251,15 +1252,15 @@ iscsi_create_flashnode_sess(struct Scsi_Host *shost, int index, ...@@ -1251,15 +1252,15 @@ iscsi_create_flashnode_sess(struct Scsi_Host *shost, int index,
err = device_register(&fnode_sess->dev); err = device_register(&fnode_sess->dev);
if (err) if (err)
goto free_fnode_sess; goto put_dev;
if (dd_size) if (dd_size)
fnode_sess->dd_data = &fnode_sess[1]; fnode_sess->dd_data = &fnode_sess[1];
return fnode_sess; return fnode_sess;
free_fnode_sess: put_dev:
kfree(fnode_sess); put_device(&fnode_sess->dev);
return NULL; return NULL;
} }
EXPORT_SYMBOL_GPL(iscsi_create_flashnode_sess); EXPORT_SYMBOL_GPL(iscsi_create_flashnode_sess);
...@@ -1299,15 +1300,15 @@ iscsi_create_flashnode_conn(struct Scsi_Host *shost, ...@@ -1299,15 +1300,15 @@ iscsi_create_flashnode_conn(struct Scsi_Host *shost,
err = device_register(&fnode_conn->dev); err = device_register(&fnode_conn->dev);
if (err) if (err)
goto free_fnode_conn; goto put_dev;
if (dd_size) if (dd_size)
fnode_conn->dd_data = &fnode_conn[1]; fnode_conn->dd_data = &fnode_conn[1];
return fnode_conn; return fnode_conn;
free_fnode_conn: put_dev:
kfree(fnode_conn); put_device(&fnode_conn->dev);
return NULL; return NULL;
} }
EXPORT_SYMBOL_GPL(iscsi_create_flashnode_conn); EXPORT_SYMBOL_GPL(iscsi_create_flashnode_conn);
...@@ -4815,7 +4816,7 @@ iscsi_register_transport(struct iscsi_transport *tt) ...@@ -4815,7 +4816,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
dev_set_name(&priv->dev, "%s", tt->name); dev_set_name(&priv->dev, "%s", tt->name);
err = device_register(&priv->dev); err = device_register(&priv->dev);
if (err) if (err)
goto free_priv; goto put_dev;
err = sysfs_create_group(&priv->dev.kobj, &iscsi_transport_group); err = sysfs_create_group(&priv->dev.kobj, &iscsi_transport_group);
if (err) if (err)
...@@ -4850,8 +4851,8 @@ iscsi_register_transport(struct iscsi_transport *tt) ...@@ -4850,8 +4851,8 @@ iscsi_register_transport(struct iscsi_transport *tt)
unregister_dev: unregister_dev:
device_unregister(&priv->dev); device_unregister(&priv->dev);
return NULL; return NULL;
free_priv: put_dev:
kfree(priv); put_device(&priv->dev);
return NULL; return NULL;
} }
EXPORT_SYMBOL_GPL(iscsi_register_transport); EXPORT_SYMBOL_GPL(iscsi_register_transport);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment