diff mbox series

[net] ipv4: remove BUG_ON() from fib_compute_spec_dst

Message ID ecd53925d2d5d5ed19c5e18b8a7998b63be39be0.1532705461.git.lorenzo.bianconi@redhat.com
State Accepted, archived
Delegated to: David Miller
Headers show
Series [net] ipv4: remove BUG_ON() from fib_compute_spec_dst | expand

Commit Message

Lorenzo Bianconi July 27, 2018, 4:15 p.m. UTC
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>
---
 net/ipv4/fib_frontend.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Comments

David Miller July 29, 2018, 2:07 a.m. UTC | #1
From: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
Date: Fri, 27 Jul 2018 18:15:46 +0200

> 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>

Applied and queued up for -stable, thank you.
diff mbox series

Patch

diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index e46cdd310e5f..2998b0e47d4b 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -292,19 +292,19 @@  __be32 fib_compute_spec_dst(struct sk_buff *skb)
 		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);
 		struct flowi4 fl4 = {
 			.flowi4_iif = LOOPBACK_IFINDEX,
 			.flowi4_oif = l3mdev_master_ifindex_rcu(dev),
 			.daddr = ip_hdr(skb)->saddr,
 			.flowi4_tos = RT_TOS(ip_hdr(skb)->tos),
 			.flowi4_scope = scope,
-			.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0,
+			.flowi4_mark = vmark ? skb->mark : 0,
 		};
 		if (!fib_lookup(net, &fl4, &res, 0))
 			return FIB_RES_PREFSRC(net, res);