mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
IB/mlx4: Fix refcount leak in add_port() error path
After kobject_init_and_add(), the lifetime of the embedded struct
kobject is expected to be managed through the kobject core reference
counting.
In add_port(), failure paths after kobject_init_and_add() must not free
struct mlx4_port directly, because the embedded kobject is then managed
by the kobject core. Freeing it directly leaves the kobject reference
counting unbalanced and can lead to incorrect lifetime handling.
Allocate the pkey and gid attribute arrays before kobject_init_and_add(),
so failures before kobject initialization can be handled by directly
freeing the allocated memory. Once kobject_init_and_add() has been
called, unwind later failures by removing any successfully created sysfs
groups, calling kobject_del(), and then releasing the embedded kobject
with kobject_put().
Fixes: c1e7e46612 ("IB/mlx4: Add iov directory in sysfs under the ib device")
Link: https://patch.msgid.link/r/20260518021910.972900-1-lgs201920130244@gmail.com
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
parent
35744ab3d0
commit
9a8826fdfb
|
|
@ -636,12 +636,6 @@ static int add_port(struct mlx4_ib_dev *dev, int port_num, int slave)
|
|||
p->port_num = port_num;
|
||||
p->slave = slave;
|
||||
|
||||
ret = kobject_init_and_add(&p->kobj, &port_type,
|
||||
kobject_get(dev->dev_ports_parent[slave]),
|
||||
"%d", port_num);
|
||||
if (ret)
|
||||
goto err_alloc;
|
||||
|
||||
p->pkey_group.name = "pkey_idx";
|
||||
p->pkey_group.attrs =
|
||||
alloc_group_attrs(show_port_pkey,
|
||||
|
|
@ -649,13 +643,9 @@ static int add_port(struct mlx4_ib_dev *dev, int port_num, int slave)
|
|||
dev->dev->caps.pkey_table_len[port_num]);
|
||||
if (!p->pkey_group.attrs) {
|
||||
ret = -ENOMEM;
|
||||
goto err_alloc;
|
||||
goto err_free_port;
|
||||
}
|
||||
|
||||
ret = sysfs_create_group(&p->kobj, &p->pkey_group);
|
||||
if (ret)
|
||||
goto err_free_pkey;
|
||||
|
||||
p->gid_group.name = "gid_idx";
|
||||
p->gid_group.attrs = alloc_group_attrs(show_port_gid_idx, NULL, 1);
|
||||
if (!p->gid_group.attrs) {
|
||||
|
|
@ -663,28 +653,47 @@ static int add_port(struct mlx4_ib_dev *dev, int port_num, int slave)
|
|||
goto err_free_pkey;
|
||||
}
|
||||
|
||||
ret = kobject_init_and_add(&p->kobj, &port_type,
|
||||
kobject_get(dev->dev_ports_parent[slave]),
|
||||
"%d", port_num);
|
||||
if (ret)
|
||||
goto err_put;
|
||||
|
||||
ret = sysfs_create_group(&p->kobj, &p->pkey_group);
|
||||
if (ret)
|
||||
goto err_del;
|
||||
|
||||
ret = sysfs_create_group(&p->kobj, &p->gid_group);
|
||||
if (ret)
|
||||
goto err_free_gid;
|
||||
goto err_remove_pkey;
|
||||
|
||||
ret = add_vf_smi_entries(p);
|
||||
if (ret)
|
||||
goto err_free_gid;
|
||||
goto err_remove_gid;
|
||||
|
||||
list_add_tail(&p->kobj.entry, &dev->pkeys.pkey_port_list[slave]);
|
||||
return 0;
|
||||
|
||||
err_free_gid:
|
||||
kfree(p->gid_group.attrs[0]);
|
||||
kfree(p->gid_group.attrs);
|
||||
err_remove_gid:
|
||||
sysfs_remove_group(&p->kobj, &p->gid_group);
|
||||
|
||||
err_remove_pkey:
|
||||
sysfs_remove_group(&p->kobj, &p->pkey_group);
|
||||
|
||||
err_del:
|
||||
kobject_del(&p->kobj);
|
||||
|
||||
err_put:
|
||||
kobject_put(dev->dev_ports_parent[slave]);
|
||||
kobject_put(&p->kobj);
|
||||
return ret;
|
||||
|
||||
err_free_pkey:
|
||||
for (i = 0; i < dev->dev->caps.pkey_table_len[port_num]; ++i)
|
||||
kfree(p->pkey_group.attrs[i]);
|
||||
kfree(p->pkey_group.attrs);
|
||||
|
||||
err_alloc:
|
||||
kobject_put(dev->dev_ports_parent[slave]);
|
||||
err_free_port:
|
||||
kfree(p);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user