Message ID | 1448131579-20525-1-git-send-email-razor@blackwall.org |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
On 11/21/15 11:46 AM, Nikolay Aleksandrov wrote: > From: Nikolay Aleksandrov<nikolay@cumulusnetworks.com> > > When vrf's ->newlink is called, if register_netdevice() fails then it > does free_netdev(), but that's also done by rtnl_newlink() so a second > free happens and memory gets corrupted, to reproduce execute the > following line a couple of times (1 - 5 usually is enough): > $ for i in `seq 1 5`; do ip link add vrf: type vrf table 1; done; > This works because we fail in register_netdevice() because of the wrong > name "vrf:". Acked-by: David Ahern <dsa@cumulusnetworks.com> Thanks, Nik. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Nikolay Aleksandrov <razor@blackwall.org> Date: Sat, 21 Nov 2015 19:46:19 +0100 > From: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> > > When vrf's ->newlink is called, if register_netdevice() fails then it > does free_netdev(), but that's also done by rtnl_newlink() so a second > free happens and memory gets corrupted, to reproduce execute the > following line a couple of times (1 - 5 usually is enough): > $ for i in `seq 1 5`; do ip link add vrf: type vrf table 1; done; > This works because we fail in register_netdevice() because of the wrong > name "vrf:". > > And here's a trace of one crash: ... > Fixes: 193125dbd8eb ("net: Introduce VRF device driver") > Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> Applied and queued up for -stable, thanks. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 92fa3e1ea65c..4f9748457f5a 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -907,7 +907,6 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { struct net_vrf *vrf = netdev_priv(dev); - int err; if (!data || !data[IFLA_VRF_TABLE]) return -EINVAL; @@ -916,15 +915,7 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev, dev->priv_flags |= IFF_L3MDEV_MASTER; - err = register_netdevice(dev); - if (err < 0) - goto out_fail; - - return 0; - -out_fail: - free_netdev(dev); - return err; + return register_netdevice(dev); } static size_t vrf_nl_getsize(const struct net_device *dev)