vxlan: fix use-after-free on deletion
Adding a vxlan interface to a socket isn't symmetrical, while adding is done in vxlan_open() the deletion is done in vxlan_dellink(). This can cause a use-after-free error when we close the vxlan interface before deleting it. We add vxlan_vs_del_dev() to match vxlan_vs_add_dev() and call it from vxlan_stop() to match the call from vxlan_open(). Fixes: 56ef9c909b40 ("vxlan: Move socket initialization to within rtnl scope") Acked-by: Jiri Benc <jbenc@redhat.com> Tested-by: Roi Dayan <roid@mellanox.com> Signed-off-by: Mark Bloch <markb@mellanox.com> Acked-by: Roopa Prabhu <roopa@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
78b07ac1e4
commit
a53cb29b0a
@ -59,6 +59,8 @@ static const u8 all_zeros_mac[ETH_ALEN + 2];
|
||||
|
||||
static int vxlan_sock_add(struct vxlan_dev *vxlan);
|
||||
|
||||
static void vxlan_vs_del_dev(struct vxlan_dev *vxlan);
|
||||
|
||||
/* per-network namespace private data for this module */
|
||||
struct vxlan_net {
|
||||
struct list_head vxlan_list;
|
||||
@ -1081,6 +1083,8 @@ static void vxlan_sock_release(struct vxlan_dev *vxlan)
|
||||
rcu_assign_pointer(vxlan->vn4_sock, NULL);
|
||||
synchronize_net();
|
||||
|
||||
vxlan_vs_del_dev(vxlan);
|
||||
|
||||
if (__vxlan_sock_release_prep(sock4)) {
|
||||
udp_tunnel_sock_release(sock4->sock);
|
||||
kfree(sock4);
|
||||
@ -2356,6 +2360,15 @@ static void vxlan_cleanup(unsigned long arg)
|
||||
mod_timer(&vxlan->age_timer, next_timer);
|
||||
}
|
||||
|
||||
static void vxlan_vs_del_dev(struct vxlan_dev *vxlan)
|
||||
{
|
||||
struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
|
||||
|
||||
spin_lock(&vn->sock_lock);
|
||||
hlist_del_init_rcu(&vxlan->hlist);
|
||||
spin_unlock(&vn->sock_lock);
|
||||
}
|
||||
|
||||
static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan)
|
||||
{
|
||||
struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
|
||||
@ -3300,15 +3313,9 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
|
||||
static void vxlan_dellink(struct net_device *dev, struct list_head *head)
|
||||
{
|
||||
struct vxlan_dev *vxlan = netdev_priv(dev);
|
||||
struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
|
||||
|
||||
vxlan_flush(vxlan, true);
|
||||
|
||||
spin_lock(&vn->sock_lock);
|
||||
if (!hlist_unhashed(&vxlan->hlist))
|
||||
hlist_del_rcu(&vxlan->hlist);
|
||||
spin_unlock(&vn->sock_lock);
|
||||
|
||||
gro_cells_destroy(&vxlan->gro_cells);
|
||||
list_del(&vxlan->next);
|
||||
unregister_netdevice_queue(dev, head);
|
||||
|
Loading…
x
Reference in New Issue
Block a user