hsr: fix a memory leak in hsr_del_port()
hsr_del_port() should release all the resources allocated in hsr_add_port(). As a consequence of this change, hsr_for_each_port() is no longer safe to work with hsr_del_port(), switch to list_for_each_entry_safe() as we always hold RTNL lock. Cc: Arvid Brodin <arvid.brodin@alten.se> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
114b5b355e
commit
619afef01f
@ -351,13 +351,14 @@ static void hsr_dev_destroy(struct net_device *hsr_dev)
|
|||||||
{
|
{
|
||||||
struct hsr_priv *hsr;
|
struct hsr_priv *hsr;
|
||||||
struct hsr_port *port;
|
struct hsr_port *port;
|
||||||
|
struct hsr_port *tmp;
|
||||||
|
|
||||||
hsr = netdev_priv(hsr_dev);
|
hsr = netdev_priv(hsr_dev);
|
||||||
|
|
||||||
hsr_debugfs_term(hsr);
|
hsr_debugfs_term(hsr);
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
hsr_for_each_port(hsr, port)
|
list_for_each_entry_safe(port, tmp, &hsr->ports, port_list)
|
||||||
hsr_del_port(port);
|
hsr_del_port(port);
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
|
|
||||||
@ -428,6 +429,7 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
|
|||||||
{
|
{
|
||||||
struct hsr_priv *hsr;
|
struct hsr_priv *hsr;
|
||||||
struct hsr_port *port;
|
struct hsr_port *port;
|
||||||
|
struct hsr_port *tmp;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
hsr = netdev_priv(hsr_dev);
|
hsr = netdev_priv(hsr_dev);
|
||||||
@ -492,7 +494,7 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
hsr_for_each_port(hsr, port)
|
list_for_each_entry_safe(port, tmp, &hsr->ports, port_list)
|
||||||
hsr_del_port(port);
|
hsr_del_port(port);
|
||||||
err_add_port:
|
err_add_port:
|
||||||
hsr_del_node(&hsr->self_node_db);
|
hsr_del_node(&hsr->self_node_db);
|
||||||
|
@ -193,4 +193,5 @@ void hsr_del_port(struct hsr_port *port)
|
|||||||
|
|
||||||
if (port != master)
|
if (port != master)
|
||||||
dev_put(port->dev);
|
dev_put(port->dev);
|
||||||
|
kfree(port);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user