[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <54E637FE.5030601@alten.se>
Date: Thu, 19 Feb 2015 20:22:38 +0100
From: Arvid Brodin <arvid.brodin@...en.se>
To: Arvid Brodin <arvid.brodin@...en.se>,
David Miller <davem@...emloft.net>,
"netdev@...r.kernel.org" <netdev@...r.kernel.org>
CC: Nicolas Dichtel <nicolas.dichtel@...nd.com>
Subject: [PATCH net] net/hsr: Fix NULL pointer dereference and refcnt bugs
when deleting a HSR interface.
How to repeat:
$ sudo ip link add hsr0 type hsr slave1 <if1> slave2 <if2>
$ sudo ip link del hsr0
BUG: unable to handle kernel NULL pointer dereference at 0000000000000018
IP: [<ffffffff8187f495>] hsr_del_port+0x15/0xa0
etc...
Reported-by: Nicolas Dichtel <nicolas.dichtel@...nd.com>
Fixes: 51f3c605318b056a ("net/hsr: Move slave init to hsr_slave.c.")
Signed-off-by: Arvid Brodin <arvid.brodin@...en.se>
---
net/hsr/hsr_device.c | 3 +++
net/hsr/hsr_main.c | 4 ++++
net/hsr/hsr_slave.c | 10 +++++++---
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
index a138d75..44d2746 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -359,8 +359,11 @@ static void hsr_dev_destroy(struct net_device *hsr_dev)
struct hsr_port *port;
hsr = netdev_priv(hsr_dev);
+
+ rtnl_lock();
hsr_for_each_port(hsr, port)
hsr_del_port(port);
+ rtnl_unlock();
del_timer_sync(&hsr->prune_timer);
del_timer_sync(&hsr->announce_timer);
diff --git a/net/hsr/hsr_main.c b/net/hsr/hsr_main.c
index 779d28b..cd37d00 100644
--- a/net/hsr/hsr_main.c
+++ b/net/hsr/hsr_main.c
@@ -36,6 +36,10 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event,
return NOTIFY_DONE; /* Not an HSR device */
hsr = netdev_priv(dev);
port = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
+ if (port == NULL) {
+ /* Resend of notification concerning removed device? */
+ return NOTIFY_DONE;
+ }
} else {
hsr = port->hsr;
}
diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c
index a348dcb..7d37366 100644
--- a/net/hsr/hsr_slave.c
+++ b/net/hsr/hsr_slave.c
@@ -181,8 +181,10 @@ void hsr_del_port(struct hsr_port *port)
list_del_rcu(&port->port_list);
if (port != master) {
- netdev_update_features(master->dev);
- dev_set_mtu(master->dev, hsr_get_max_mtu(hsr));
+ if (master != NULL) {
+ netdev_update_features(master->dev);
+ dev_set_mtu(master->dev, hsr_get_max_mtu(hsr));
+ }
netdev_rx_handler_unregister(port->dev);
dev_set_promiscuity(port->dev, -1);
}
@@ -192,5 +194,7 @@ void hsr_del_port(struct hsr_port *port)
*/
synchronize_rcu();
- dev_put(port->dev);
+
+ if (port != master)
+ dev_put(port->dev);
}
--
2.0.4
--
Arvid Brodin | Consultant (Linux)
ALTEN | Knarrarnäsgatan 7 | SE-164 40 Kista | Sweden
arvid.brodin@...en.se | www.alten.se/en/
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists