Jiri Slaby f15162
From: Sabrina Dubroca <sd@queasysnail.net>
Jiri Slaby f15162
Date: Sat, 30 Jun 2018 17:38:55 +0200
Jiri Slaby f15162
Subject: net: fix use-after-free in GRO with ESP
Jiri Slaby f15162
Git-commit: 603d4cf8fe095b1ee78f423d514427be507fb513
Jiri Slaby f15162
Patch-mainline: v4.18-rc4
Jiri Slaby f15162
References: networking-stable-18_07_19
Jiri Slaby f15162
Jiri Slaby f15162
Since the addition of GRO for ESP, gro_receive can consume the skb and
Jiri Slaby f15162
return -EINPROGRESS. In that case, the lower layer GRO handler cannot
Jiri Slaby f15162
touch the skb anymore.
Jiri Slaby f15162
Jiri Slaby f15162
Commit 5f114163f2f5 ("net: Add a skb_gro_flush_final helper.") converted
Jiri Slaby f15162
some of the gro_receive handlers that can lead to ESP's gro_receive so
Jiri Slaby f15162
that they wouldn't access the skb when -EINPROGRESS is returned, but
Jiri Slaby f15162
missed other spots, mainly in tunneling protocols.
Jiri Slaby f15162
Jiri Slaby f15162
This patch finishes the conversion to using skb_gro_flush_final(), and
Jiri Slaby f15162
adds a new helper, skb_gro_flush_final_remcsum(), used in VXLAN and
Jiri Slaby f15162
GUE.
Jiri Slaby f15162
Jiri Slaby f15162
Fixes: 5f114163f2f5 ("net: Add a skb_gro_flush_final helper.")
Jiri Slaby f15162
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Jiri Slaby f15162
Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
Jiri Slaby f15162
Signed-off-by: David S. Miller <davem@davemloft.net>
Jiri Slaby f15162
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Jiri Slaby f15162
---
Jiri Slaby f15162
 drivers/net/geneve.c      |  2 +-
Jiri Slaby f15162
 drivers/net/vxlan.c       |  4 +---
Jiri Slaby f15162
 include/linux/netdevice.h | 20 ++++++++++++++++++++
Jiri Slaby f15162
 net/8021q/vlan.c          |  2 +-
Jiri Slaby f15162
 net/ipv4/fou.c            |  4 +---
Jiri Slaby f15162
 net/ipv4/gre_offload.c    |  2 +-
Jiri Slaby f15162
 net/ipv4/udp_offload.c    |  2 +-
Jiri Slaby f15162
 7 files changed, 26 insertions(+), 10 deletions(-)
Jiri Slaby f15162
Jiri Slaby f15162
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
Jiri Slaby f15162
index 750eaa53bf0c..ada33c2d9ac2 100644
Jiri Slaby f15162
--- a/drivers/net/geneve.c
Jiri Slaby f15162
+++ b/drivers/net/geneve.c
Jiri Slaby f15162
@@ -476,7 +476,7 @@ static struct sk_buff **geneve_gro_receive(struct sock *sk,
Jiri Slaby f15162
 out_unlock:
Jiri Slaby f15162
 	rcu_read_unlock();
Jiri Slaby f15162
 out:
Jiri Slaby f15162
-	NAPI_GRO_CB(skb)->flush |= flush;
Jiri Slaby f15162
+	skb_gro_flush_final(skb, pp, flush);
Jiri Slaby f15162
 
Jiri Slaby f15162
 	return pp;
Jiri Slaby f15162
 }
Jiri Slaby f15162
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
Jiri Slaby f15162
index aee0e60471f1..f6bb1d54d4bd 100644
Jiri Slaby f15162
--- a/drivers/net/vxlan.c
Jiri Slaby f15162
+++ b/drivers/net/vxlan.c
Jiri Slaby f15162
@@ -623,9 +623,7 @@ static struct sk_buff **vxlan_gro_receive(struct sock *sk,
Jiri Slaby f15162
 	flush = 0;
Jiri Slaby f15162
 
Jiri Slaby f15162
 out:
Jiri Slaby f15162
-	skb_gro_remcsum_cleanup(skb, &grc;;
Jiri Slaby f15162
-	skb->remcsum_offload = 0;
Jiri Slaby f15162
-	NAPI_GRO_CB(skb)->flush |= flush;
Jiri Slaby f15162
+	skb_gro_flush_final_remcsum(skb, pp, flush, &grc;;
Jiri Slaby f15162
 
Jiri Slaby f15162
 	return pp;
Jiri Slaby f15162
 }
Jiri Slaby f15162
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
Jiri Slaby f15162
index 3ec9850c7936..3d0cc0b5cec2 100644
Jiri Slaby f15162
--- a/include/linux/netdevice.h
Jiri Slaby f15162
+++ b/include/linux/netdevice.h
Jiri Slaby f15162
@@ -2789,11 +2789,31 @@ static inline void skb_gro_flush_final(struct sk_buff *skb, struct sk_buff **pp,
Jiri Slaby f15162
 	if (PTR_ERR(pp) != -EINPROGRESS)
Jiri Slaby f15162
 		NAPI_GRO_CB(skb)->flush |= flush;
Jiri Slaby f15162
 }
Jiri Slaby f15162
+static inline void skb_gro_flush_final_remcsum(struct sk_buff *skb,
Jiri Slaby f15162
+					       struct sk_buff **pp,
Jiri Slaby f15162
+					       int flush,
Jiri Slaby f15162
+					       struct gro_remcsum *grc)
Jiri Slaby f15162
+{
Jiri Slaby f15162
+	if (PTR_ERR(pp) != -EINPROGRESS) {
Jiri Slaby f15162
+		NAPI_GRO_CB(skb)->flush |= flush;
Jiri Slaby f15162
+		skb_gro_remcsum_cleanup(skb, grc);
Jiri Slaby f15162
+		skb->remcsum_offload = 0;
Jiri Slaby f15162
+	}
Jiri Slaby f15162
+}
Jiri Slaby f15162
 #else
Jiri Slaby f15162
 static inline void skb_gro_flush_final(struct sk_buff *skb, struct sk_buff **pp, int flush)
Jiri Slaby f15162
 {
Jiri Slaby f15162
 	NAPI_GRO_CB(skb)->flush |= flush;
Jiri Slaby f15162
 }
Jiri Slaby f15162
+static inline void skb_gro_flush_final_remcsum(struct sk_buff *skb,
Jiri Slaby f15162
+					       struct sk_buff **pp,
Jiri Slaby f15162
+					       int flush,
Jiri Slaby f15162
+					       struct gro_remcsum *grc)
Jiri Slaby f15162
+{
Jiri Slaby f15162
+	NAPI_GRO_CB(skb)->flush |= flush;
Jiri Slaby f15162
+	skb_gro_remcsum_cleanup(skb, grc);
Jiri Slaby f15162
+	skb->remcsum_offload = 0;
Jiri Slaby f15162
+}
Jiri Slaby f15162
 #endif
Jiri Slaby f15162
 
Jiri Slaby f15162
 static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev,
Jiri Slaby f15162
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
Jiri Slaby f15162
index 73a65789271b..8ccee3d01822 100644
Jiri Slaby f15162
--- a/net/8021q/vlan.c
Jiri Slaby f15162
+++ b/net/8021q/vlan.c
Jiri Slaby f15162
@@ -693,7 +693,7 @@ static struct sk_buff **vlan_gro_receive(struct sk_buff **head,
Jiri Slaby f15162
 out_unlock:
Jiri Slaby f15162
 	rcu_read_unlock();
Jiri Slaby f15162
 out:
Jiri Slaby f15162
-	NAPI_GRO_CB(skb)->flush |= flush;
Jiri Slaby f15162
+	skb_gro_flush_final(skb, pp, flush);
Jiri Slaby f15162
 
Jiri Slaby f15162
 	return pp;
Jiri Slaby f15162
 }
Jiri Slaby f15162
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
Jiri Slaby f15162
index 1540db65241a..c9ec1603666b 100644
Jiri Slaby f15162
--- a/net/ipv4/fou.c
Jiri Slaby f15162
+++ b/net/ipv4/fou.c
Jiri Slaby f15162
@@ -448,9 +448,7 @@ static struct sk_buff **gue_gro_receive(struct sock *sk,
Jiri Slaby f15162
 out_unlock:
Jiri Slaby f15162
 	rcu_read_unlock();
Jiri Slaby f15162
 out:
Jiri Slaby f15162
-	NAPI_GRO_CB(skb)->flush |= flush;
Jiri Slaby f15162
-	skb_gro_remcsum_cleanup(skb, &grc;;
Jiri Slaby f15162
-	skb->remcsum_offload = 0;
Jiri Slaby f15162
+	skb_gro_flush_final_remcsum(skb, pp, flush, &grc;;
Jiri Slaby f15162
 
Jiri Slaby f15162
 	return pp;
Jiri Slaby f15162
 }
Jiri Slaby f15162
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c
Jiri Slaby f15162
index 1859c473b21a..6a7d980105f6 100644
Jiri Slaby f15162
--- a/net/ipv4/gre_offload.c
Jiri Slaby f15162
+++ b/net/ipv4/gre_offload.c
Jiri Slaby f15162
@@ -223,7 +223,7 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head,
Jiri Slaby f15162
 out_unlock:
Jiri Slaby f15162
 	rcu_read_unlock();
Jiri Slaby f15162
 out:
Jiri Slaby f15162
-	NAPI_GRO_CB(skb)->flush |= flush;
Jiri Slaby f15162
+	skb_gro_flush_final(skb, pp, flush);
Jiri Slaby f15162
 
Jiri Slaby f15162
 	return pp;
Jiri Slaby f15162
 }
Jiri Slaby f15162
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
Jiri Slaby f15162
index 92dc9e5a7ff3..69c54540d5b4 100644
Jiri Slaby f15162
--- a/net/ipv4/udp_offload.c
Jiri Slaby f15162
+++ b/net/ipv4/udp_offload.c
Jiri Slaby f15162
@@ -394,7 +394,7 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb,
Jiri Slaby f15162
 out_unlock:
Jiri Slaby f15162
 	rcu_read_unlock();
Jiri Slaby f15162
 out:
Jiri Slaby f15162
-	NAPI_GRO_CB(skb)->flush |= flush;
Jiri Slaby f15162
+	skb_gro_flush_final(skb, pp, flush);
Jiri Slaby f15162
 	return pp;
Jiri Slaby f15162
 }
Jiri Slaby f15162
 EXPORT_SYMBOL(udp_gro_receive);
Jiri Slaby f15162
-- 
Jiri Slaby f15162
2.18.0
Jiri Slaby f15162