]>
Commit | Line | Data |
---|---|---|
38568109 GKH |
1 | From foo@baz Thu Mar 28 21:54:17 CET 2019 |
2 | From: Zhiqiang Liu <liuzhiqiang26@huawei.com> | |
3 | Date: Sat, 16 Mar 2019 17:02:54 +0800 | |
4 | Subject: vxlan: Don't call gro_cells_destroy() before device is unregistered | |
5 | ||
6 | From: Zhiqiang Liu <liuzhiqiang26@huawei.com> | |
7 | ||
8 | [ Upstream commit cc4807bb609230d8959fd732b0bf3bd4c2de8eac ] | |
9 | ||
10 | Commit ad6c9986bcb62 ("vxlan: Fix GRO cells race condition between | |
11 | receive and link delete") fixed a race condition for the typical case a vxlan | |
12 | device is dismantled from the current netns. But if a netns is dismantled, | |
13 | vxlan_destroy_tunnels() is called to schedule a unregister_netdevice_queue() | |
14 | of all the vxlan tunnels that are related to this netns. | |
15 | ||
16 | In vxlan_destroy_tunnels(), gro_cells_destroy() is called and finished before | |
17 | unregister_netdevice_queue(). This means that the gro_cells_destroy() call is | |
18 | done too soon, for the same reasons explained in above commit. | |
19 | ||
20 | So we need to fully respect the RCU rules, and thus must remove the | |
21 | gro_cells_destroy() call or risk use after-free. | |
22 | ||
23 | Fixes: 58ce31cca1ff ("vxlan: GRO support at tunnel layer") | |
24 | Signed-off-by: Suanming.Mou <mousuanming@huawei.com> | |
25 | Suggested-by: Eric Dumazet <eric.dumazet@gmail.com> | |
26 | Reviewed-by: Stefano Brivio <sbrivio@redhat.com> | |
27 | Reviewed-by: Zhiqiang Liu <liuzhiqiang26@huawei.com> | |
28 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
29 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
30 | --- | |
31 | drivers/net/vxlan.c | 4 +--- | |
32 | 1 file changed, 1 insertion(+), 3 deletions(-) | |
33 | ||
34 | --- a/drivers/net/vxlan.c | |
35 | +++ b/drivers/net/vxlan.c | |
36 | @@ -3798,10 +3798,8 @@ static void vxlan_destroy_tunnels(struct | |
37 | /* If vxlan->dev is in the same netns, it has already been added | |
38 | * to the list by the previous loop. | |
39 | */ | |
40 | - if (!net_eq(dev_net(vxlan->dev), net)) { | |
41 | - gro_cells_destroy(&vxlan->gro_cells); | |
42 | + if (!net_eq(dev_net(vxlan->dev), net)) | |
43 | unregister_netdevice_queue(vxlan->dev, head); | |
44 | - } | |
45 | } | |
46 | ||
47 | for (h = 0; h < PORT_HASH_SIZE; ++h) |