Patch "vxlan: fix hlist corruption" has been added to the 4.11-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
vxlan: fix hlist corruption
to the 4.11-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
vxlan-fix-hlist-corruption.patch
and it can be found in the queue-4.11 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From foo@baz Mon Jul 17 18:47:09 CEST 2017
From: Jiri Benc <[email protected]>
Date: Sun, 2 Jul 2017 19:00:57 +0200
Subject: vxlan: fix hlist corruption
From: Jiri Benc <[email protected]>
[ Upstream commit 69e766612c4bcb79e19cebed9eed61d4222c1d47 ]
It's not a good idea to add the same hlist_node to two different hash lists. This leads to various hard to debug memory corruptions.
--- drivers/net/vxlan.c | 30 ++++++++++++++++++++---------- include/net/vxlan.h | 10 +++++++++- 2 files changed, 29 insertions(+), 11 deletions(-)
drivers/net/vxlan.c +20 -10
@@ -228,15 +228,15 @@ static struct vxlan_sock *vxlan_find_socstatic struct vxlan_dev *vxlan_vs_find_vni (struct vxlan_sock *vs,__be32 vni) { -struct vxlan_dev *vxlan; +struct vxlan_dev_node *node;/* For flow based devices, map all packets to VNI 0 */ if (vs->flags &VXLAN_F_COLLECT_METADATA ) vni =0 ; -hlist_for_each_entry_rcu (vxlan,vni_head (vs, vni), hlist) { -if (vxlan->default_dst.remote_vni == vni) -return vxlan; +hlist_for_each_entry_rcu (node,vni_head (vs, vni), hlist) { +if (node->vxlan->default_dst.remote_vni == vni) +return node->vxlan; }return NULL ;
@@ -2361,17 +2361,22 @@ static void vxlan_vs_del_dev(struct vxlastruct vxlan_net *vn =net_generic (vxlan->net, vxlan_net_id);spin_lock (&vn->sock_lock); -hlist_del_init_rcu (&vxlan->hlist); +hlist_del_init_rcu (&vxlan->hlist4.hlist); +#if IS_ENABLED (CONFIG_IPV6 ) +hlist_del_init_rcu (&vxlan->hlist6.hlist); +#endif spin_unlock (&vn->sock_lock); } -static void vxlan_vs_add_dev (struct vxlan_sock *vs,struct vxlan_dev *vxlan) +static void vxlan_vs_add_dev (struct vxlan_sock *vs,struct vxlan_dev *vxlan, +struct vxlan_dev_node *node) {struct vxlan_net *vn =net_generic (vxlan->net, vxlan_net_id);__be32 vni = vxlan->default_dst.remote_vni; + node->vxlan = vxlan;spin_lock (&vn->sock_lock); -hlist_add_head_rcu (&vxlan->hlist,vni_head (vs, vni)); +hlist_add_head_rcu (&node->hlist,vni_head (vs, vni));spin_unlock (&vn->sock_lock); }
@@ -2817,6 +2822,7 @@ static int __vxlan_sock_add(struct vxlan {struct vxlan_net *vn =net_generic (vxlan->net, vxlan_net_id);struct vxlan_sock *vs =NULL ; +struct vxlan_dev_node *node;if (!vxlan->cfg.no_share) {spin_lock (&vn->sock_lock);
@@ -2834,12 +2840,16 @@ static int __vxlan_sock_add(struct vxlanif (IS_ERR (vs))return PTR_ERR (vs);#if IS_ENABLED (CONFIG_IPV6 ) -if (ipv6) +if (ipv6) {rcu_assign_pointer (vxlan->vn6_sock, vs); - else + node = &vxlan->hlist6; + } else#endif + {rcu_assign_pointer (vxlan->vn4_sock, vs); -vxlan_vs_add_dev (vs, vxlan); + node = &vxlan->hlist4; + } +vxlan_vs_add_dev (vs, vxlan, node);return 0 ; }
include/net/vxlan.h +9 -1
@@ -221,9 +221,17 @@ struct vxlan_config {bool no_share; }; +struct vxlan_dev_node { +struct hlist_node hlist; +struct vxlan_dev *vxlan; +}; +/* Pseudo network device */ struct vxlan_dev { -struct hlist_node hlist;/* vni hash table */ +struct vxlan_dev_node hlist4;/* vni hash table for IPv4 socket */ +#if IS_ENABLED (CONFIG_IPV6 ) +struct vxlan_dev_node hlist6;/* vni hash table for IPv6 socket */ +#endif struct list_head next;/* vxlan's per namespace list */ struct vxlan_sock __rcu *vn4_sock;/* listening socket for IPv4 */ #if IS_ENABLED (CONFIG_IPV6 )
Patches currently in stable-queue which might be from [email protected] are
queue-4.11/geneve-fix-hlist-corruption.patchqueue-4.11/vxlan-fix-hlist-corruption.patch