]>
Commit | Line | Data |
---|---|---|
e4629b89 GKH |
1 | From foo@baz Fri Mar 15 21:29:00 PDT 2019 |
2 | From: Eric Dumazet <edumazet@google.com> | |
3 | Date: Sun, 10 Mar 2019 10:36:40 -0700 | |
4 | Subject: vxlan: test dev->flags & IFF_UP before calling gro_cells_receive() | |
5 | ||
6 | From: Eric Dumazet <edumazet@google.com> | |
7 | ||
8 | [ Upstream commit 59cbf56fcd98ba2a715b6e97c4e43f773f956393 ] | |
9 | ||
10 | Same reasons than the ones explained in commit 4179cb5a4c92 | |
11 | ("vxlan: test dev->flags & IFF_UP before calling netif_rx()") | |
12 | ||
13 | netif_rx() or gro_cells_receive() must be called under a strict contract. | |
14 | ||
15 | At device dismantle phase, core networking clears IFF_UP | |
16 | and flush_all_backlogs() is called after rcu grace period | |
17 | to make sure no incoming packet might be in a cpu backlog | |
18 | and still referencing the device. | |
19 | ||
20 | A similar protocol is used for gro_cells infrastructure, as | |
21 | gro_cells_destroy() will be called only after a full rcu | |
22 | grace period is observed after IFF_UP has been cleared. | |
23 | ||
24 | Most drivers call netif_rx() from their interrupt handler, | |
25 | and since the interrupts are disabled at device dismantle, | |
26 | netif_rx() does not have to check dev->flags & IFF_UP | |
27 | ||
28 | Virtual drivers do not have this guarantee, and must | |
29 | therefore make the check themselves. | |
30 | ||
31 | Otherwise we risk use-after-free and/or crashes. | |
32 | ||
33 | Fixes: d342894c5d2f ("vxlan: virtual extensible lan") | |
34 | Signed-off-by: Eric Dumazet <edumazet@google.com> | |
35 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
36 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
37 | --- | |
38 | drivers/net/vxlan.c | 10 ++++++++++ | |
39 | 1 file changed, 10 insertions(+) | |
40 | ||
41 | --- a/drivers/net/vxlan.c | |
42 | +++ b/drivers/net/vxlan.c | |
43 | @@ -1238,6 +1238,14 @@ static void vxlan_rcv(struct vxlan_sock | |
44 | } | |
45 | } | |
46 | ||
47 | + rcu_read_lock(); | |
48 | + | |
49 | + if (unlikely(!(vxlan->dev->flags & IFF_UP))) { | |
50 | + rcu_read_unlock(); | |
51 | + atomic_long_inc(&vxlan->dev->rx_dropped); | |
52 | + goto drop; | |
53 | + } | |
54 | + | |
55 | stats = this_cpu_ptr(vxlan->dev->tstats); | |
56 | u64_stats_update_begin(&stats->syncp); | |
57 | stats->rx_packets++; | |
58 | @@ -1246,6 +1254,8 @@ static void vxlan_rcv(struct vxlan_sock | |
59 | ||
60 | netif_rx(skb); | |
61 | ||
62 | + rcu_read_unlock(); | |
63 | + | |
64 | return; | |
65 | drop: | |
66 | /* Consume bad packet */ |