Patch "geneve: fix hlist corruption" has been added to the 4.11-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
geneve: 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:
geneve-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:58 +0200
Subject: geneve: fix hlist corruption
From: Jiri Benc <[email protected]>
[ Upstream commit 4b4c21fad6ae6bd58ff1566f23b0f4f70fdc9a30 ]
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/geneve.c | 48 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-)
drivers/net/geneve.c +32 -16
@@ -45,9 +45,17 @@ struct geneve_net {static unsigned int geneve_net_id; +struct geneve_dev_node { +struct hlist_node hlist; +struct geneve_dev *geneve; +}; +/* Pseudo network device */ struct geneve_dev { -struct hlist_node hlist;/* vni hash table */ +struct geneve_dev_node hlist4;/* vni hash table for IPv4 socket */ +#if IS_ENABLED (CONFIG_IPV6 ) +struct geneve_dev_node hlist6;/* vni hash table for IPv6 socket */ +#endif struct net *net;/* netns for packet i/o */ struct net_device *dev;/* netdev for geneve tunnel */ struct ip_tunnel_info info;
@@ -123,16 +131,16 @@ static struct geneve_dev *geneve_lookup( __be32 addr, u8 vni[]) { struct hlist_head *vni_list_head; -struct geneve_dev *geneve; +struct geneve_dev_node *node;__u32 hash;/* Find the device for this VNI */ hash =geneve_net_vni_hash (vni); vni_list_head = &gs->vni_list[hash]; -hlist_for_each_entry_rcu (geneve, vni_list_head, hlist) { -if (eq_tun_id_and_vni ((u8 *)&geneve->info.key.tun_id, vni) && - addr == geneve->info.key.u.ipv4.dst) -return geneve; +hlist_for_each_entry_rcu (node, vni_list_head, hlist) { +if (eq_tun_id_and_vni ((u8 *)&node->geneve->info.key.tun_id, vni) && + addr == node->geneve->info.key.u.ipv4.dst) +return node->geneve; }return NULL ; }
@@ -142,16 +150,16 @@ static struct geneve_dev *geneve6_lookup struct in6_addr addr6, u8 vni[]) { struct hlist_head *vni_list_head; -struct geneve_dev *geneve; +struct geneve_dev_node *node;__u32 hash;/* Find the device for this VNI */ hash =geneve_net_vni_hash (vni); vni_list_head = &gs->vni_list[hash]; -hlist_for_each_entry_rcu (geneve, vni_list_head, hlist) { -if (eq_tun_id_and_vni ((u8 *)&geneve->info.key.tun_id, vni) && -ipv6_addr_equal (&addr6, &geneve->info.key.u.ipv6.dst)) -return geneve; +hlist_for_each_entry_rcu (node, vni_list_head, hlist) { +if (eq_tun_id_and_vni ((u8 *)&node->geneve->info.key.tun_id, vni) && +ipv6_addr_equal (&addr6, &node->geneve->info.key.u.ipv6.dst)) +return node->geneve; }return NULL ; }
@@ -579,6 +587,7 @@ static int geneve_sock_add(struct geneve {struct net *net = geneve->net;struct geneve_net *gn =net_generic (net, geneve_net_id); +struct geneve_dev_node *node;struct geneve_sock *gs;__u8 vni[3 ];__u32 hash;
@@ -597,15 +606,20 @@ static int geneve_sock_add(struct geneve out: gs->collect_md = geneve->collect_md;#if IS_ENABLED (CONFIG_IPV6 ) -if (ipv6) +if (ipv6) {rcu_assign_pointer (geneve->sock6, gs); - else + node = &geneve->hlist6; + } else#endif + {rcu_assign_pointer (geneve->sock4, gs); + node = &geneve->hlist4; + } + node->geneve = geneve;tunnel_id_to_vni (geneve->info.key.tun_id, vni); hash =geneve_net_vni_hash (vni); -hlist_add_head_rcu (&geneve->hlist, &gs->vni_list[hash]); +hlist_add_head_rcu (&node->hlist, &gs->vni_list[hash]);return 0 ; }
@@ -632,8 +646,10 @@ static int geneve_stop(struct net_device {struct geneve_dev *geneve =netdev_priv (dev); -if (!hlist_unhashed (&geneve->hlist)) -hlist_del_rcu (&geneve->hlist); +hlist_del_init_rcu (&geneve->hlist4.hlist); +#if IS_ENABLED (CONFIG_IPV6 ) +hlist_del_init_rcu (&geneve->hlist6.hlist); +#endif geneve_sock_release (geneve);return 0 ; }
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