summaryrefslogtreecommitdiffstats
path: root/net/hsr
diff options
context:
space:
mode:
authorCong Wang <xiyou.wangcong@gmail.com>2019-07-03 20:21:12 -0400
committerDavid S. Miller <davem@davemloft.net>2019-07-05 18:22:27 -0400
commit619afef01f74f3572b5e9a266c1230dc83761eec (patch)
tree655b4815bf5014dda535cdc8b4c4527ebf48909a /net/hsr
parent114b5b355ec0b6e83a6628a5ab5d03e50fd40a31 (diff)
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>
Diffstat (limited to 'net/hsr')
-rw-r--r--net/hsr/hsr_device.c6
-rw-r--r--net/hsr/hsr_slave.c1
2 files changed, 5 insertions, 2 deletions
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
index 15c72065df79..f48b6a275cf0 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -351,13 +351,14 @@ static void hsr_dev_destroy(struct net_device *hsr_dev)
351{ 351{
352 struct hsr_priv *hsr; 352 struct hsr_priv *hsr;
353 struct hsr_port *port; 353 struct hsr_port *port;
354 struct hsr_port *tmp;
354 355
355 hsr = netdev_priv(hsr_dev); 356 hsr = netdev_priv(hsr_dev);
356 357
357 hsr_debugfs_term(hsr); 358 hsr_debugfs_term(hsr);
358 359
359 rtnl_lock(); 360 rtnl_lock();
360 hsr_for_each_port(hsr, port) 361 list_for_each_entry_safe(port, tmp, &hsr->ports, port_list)
361 hsr_del_port(port); 362 hsr_del_port(port);
362 rtnl_unlock(); 363 rtnl_unlock();
363 364
@@ -428,6 +429,7 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
428{ 429{
429 struct hsr_priv *hsr; 430 struct hsr_priv *hsr;
430 struct hsr_port *port; 431 struct hsr_port *port;
432 struct hsr_port *tmp;
431 int res; 433 int res;
432 434
433 hsr = netdev_priv(hsr_dev); 435 hsr = netdev_priv(hsr_dev);
@@ -492,7 +494,7 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
492 return 0; 494 return 0;
493 495
494fail: 496fail:
495 hsr_for_each_port(hsr, port) 497 list_for_each_entry_safe(port, tmp, &hsr->ports, port_list)
496 hsr_del_port(port); 498 hsr_del_port(port);
497err_add_port: 499err_add_port:
498 hsr_del_node(&hsr->self_node_db); 500 hsr_del_node(&hsr->self_node_db);
diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c
index 88b6705ded83..ee561297d8a7 100644
--- a/net/hsr/hsr_slave.c
+++ b/net/hsr/hsr_slave.c
@@ -193,4 +193,5 @@ void hsr_del_port(struct hsr_port *port)
193 193
194 if (port != master) 194 if (port != master)
195 dev_put(port->dev); 195 dev_put(port->dev);
196 kfree(port);
196} 197}