After a bonding master reclaims the netpoll info struct, slaves could still hold a pointer to the reclaimed data. This patch fixes it: as soon as netpoll_async_cleanup is called for a slave (eg. when un-enslaved), we make sure that this slave doesn't point to the data.
The style of this patch is not nice, but it represents the simplest fix. The function is restructured by the next patch anyway ("netpoll: avoid reference leaks"). Tested: One way to reproduce the panic is with netconsole: with the script below run in a loop without this patch. Same procedure with this patch can run without panic. CONFIG_NETCONSOLE=m CONFIG_NETCONSOLE_DYNAMIC=y Then run in a loop (dual port NIC makes it easier to crash): ifconfig eth0 192.168.42.4 up ifconfig eth1 192.168.56.4 up sleep 10 modprobe -r netconsole modprobe -r bonding modprobe netconsole modprobe bonding mode=4 echo +bond0 > /sys/class/net/bonding_masters ifconfig bond0 192.168.56.3 up mkdir /sys/kernel/config/netconsole/blah echo 0 > /sys/kernel/config/netconsole/blah/enabled echo bond0 > /sys/kernel/config/netconsole/blah/dev_name echo 192.168.56.42 > /sys/kernel/config/netconsole/blah/remote_ip echo 1 > /sys/kernel/config/netconsole/blah/enabled # npinfo refcnt ->1 ifenslave bond0 eth1 # npinfo refcnt ->2 ifenslave bond0 eth0 # (this should be optional, preventing ndo_cleanup_nepoll below) # npinfo refcnt ->3 sleep 3 ifenslave -d bond0 eth1 # npinfo refcnt ->2, eth1 keeps ptr to npinfo reclaimed later => garbage sleep 1 echo -bond0 > /sys/class/net/bonding_masters # netpoll_cleanup(bond0) + dec(refcnt) # (should be optional: becomes -> 1 (aka. != 0) # ==> do not call ndo_cleanup_nepoll) # try to increase chance of writing garbage onto npinfo: ls -lR / 2>&1 | tail -30 echo +bond0 > /sys/class/net/bonding_masters ifconfig bond0 192.168.56.3 up ifenslave bond0 eth1 # dev_open() called --> netpoll_rx_disable() + npinfo is garbage # -> down(&ni->dev_lock); Signed-off-by: David Decotigny <de...@googlers.com> --- net/core/netpoll.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index e33937f..907fb5e 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -822,7 +822,8 @@ void __netpoll_cleanup(struct netpoll *np) RCU_INIT_POINTER(np->dev->npinfo, NULL); call_rcu_bh(&npinfo->rcu, rcu_cleanup_netpoll_info); - } + } else + RCU_INIT_POINTER(np->dev->npinfo, NULL); } EXPORT_SYMBOL_GPL(__netpoll_cleanup); -- 2.0.0.526.g5318336 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/