| From: Lorenzo Bianconi <lorenzo.bianconi@redhat.com> |
| Date: Fri, 27 Jul 2018 18:15:46 +0200 |
| Subject: ipv4: remove BUG_ON() from fib_compute_spec_dst |
| |
| commit 9fc12023d6f51551d6ca9ed7e02ecc19d79caf17 upstream. |
| |
| Remove BUG_ON() from fib_compute_spec_dst routine and check |
| in_dev pointer during flowi4 data structure initialization. |
| fib_compute_spec_dst routine can be run concurrently with device removal |
| where ip_ptr net_device pointer is set to NULL. This can happen |
| if userspace enables pkt info on UDP rx socket and the device |
| is removed while traffic is flowing |
| |
| Fixes: 35ebf65e851c ("ipv4: Create and use fib_compute_spec_dst() helper") |
| Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| [bwh: Backported to 3.16: adjust context] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| --- a/net/ipv4/fib_frontend.c |
| +++ b/net/ipv4/fib_frontend.c |
| @@ -209,19 +209,20 @@ __be32 fib_compute_spec_dst(struct sk_bu |
| return ip_hdr(skb)->daddr; |
| |
| in_dev = __in_dev_get_rcu(dev); |
| - BUG_ON(!in_dev); |
| |
| net = dev_net(dev); |
| |
| scope = RT_SCOPE_UNIVERSE; |
| if (!ipv4_is_zeronet(ip_hdr(skb)->saddr)) { |
| + bool vmark = in_dev && IN_DEV_SRC_VMARK(in_dev); |
| + |
| fl4.flowi4_oif = 0; |
| fl4.flowi4_iif = LOOPBACK_IFINDEX; |
| fl4.daddr = ip_hdr(skb)->saddr; |
| fl4.saddr = 0; |
| fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos); |
| fl4.flowi4_scope = scope; |
| - fl4.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0; |
| + fl4.flowi4_mark = vmark ? skb->mark : 0; |
| if (!fib_lookup(net, &fl4, &res)) |
| return FIB_RES_PREFSRC(net, res); |
| } else { |