FAILED: patch "[PATCH] geneve: fix hlist corruption" failed to apply to 4.9-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
4b4c21fad6ae6bd58ff1566f23b0f4f70fdc9a30Mon Sep 17 00:00:00 2001
From: Jiri Benc <[email protected]>
Date: Sun, 2 Jul 2017 19:00:58 +0200
Subject: [PATCH] geneve: fix hlist corruption
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.
Fixes 8ed66f0e8235 ("geneve: implement support for IPv6-based tunnels")
Cc John W. Linville <[email protected]>
Signed-off-by Jiri Benc <[email protected]>
Signed-off-by David S. Miller <[email protected]>
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(struct geneve_sock *gs, __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 geneve_sock *gs, 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 ; }
@@ -591,6 +599,7 @@ static int geneve_sock_add(struct geneve_dev *geneve, bool ipv6) {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;
@@ -609,15 +618,20 @@ static int geneve_sock_add(struct geneve_dev *geneve, bool ipv6) 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 ; }
@@ -644,8 +658,10 @@ static int geneve_stop(struct net_device *dev) {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 ; }