Commit 603d4cf8 authored by Sabrina Dubroca's avatar Sabrina Dubroca Committed by David S. Miller

net: fix use-after-free in GRO with ESP

Since the addition of GRO for ESP, gro_receive can consume the skb and
return -EINPROGRESS. In that case, the lower layer GRO handler cannot
touch the skb anymore.

Commit 5f114163 ("net: Add a skb_gro_flush_final helper.") converted
some of the gro_receive handlers that can lead to ESP's gro_receive so
that they wouldn't access the skb when -EINPROGRESS is returned, but
missed other spots, mainly in tunneling protocols.

This patch finishes the conversion to using skb_gro_flush_final(), and
adds a new helper, skb_gro_flush_final_remcsum(), used in VXLAN and
GUE.

Fixes: 5f114163 ("net: Add a skb_gro_flush_final helper.")
Signed-off-by: default avatarSabrina Dubroca <sd@queasysnail.net>
Reviewed-by: default avatarStefano Brivio <sbrivio@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1236f22f
...@@ -476,7 +476,7 @@ static struct sk_buff **geneve_gro_receive(struct sock *sk, ...@@ -476,7 +476,7 @@ static struct sk_buff **geneve_gro_receive(struct sock *sk,
out_unlock: out_unlock:
rcu_read_unlock(); rcu_read_unlock();
out: out:
NAPI_GRO_CB(skb)->flush |= flush; skb_gro_flush_final(skb, pp, flush);
return pp; return pp;
} }
......
...@@ -623,9 +623,7 @@ static struct sk_buff **vxlan_gro_receive(struct sock *sk, ...@@ -623,9 +623,7 @@ static struct sk_buff **vxlan_gro_receive(struct sock *sk,
flush = 0; flush = 0;
out: out:
skb_gro_remcsum_cleanup(skb, &grc); skb_gro_flush_final_remcsum(skb, pp, flush, &grc);
skb->remcsum_offload = 0;
NAPI_GRO_CB(skb)->flush |= flush;
return pp; return pp;
} }
......
...@@ -2789,11 +2789,31 @@ static inline void skb_gro_flush_final(struct sk_buff *skb, struct sk_buff **pp, ...@@ -2789,11 +2789,31 @@ static inline void skb_gro_flush_final(struct sk_buff *skb, struct sk_buff **pp,
if (PTR_ERR(pp) != -EINPROGRESS) if (PTR_ERR(pp) != -EINPROGRESS)
NAPI_GRO_CB(skb)->flush |= flush; NAPI_GRO_CB(skb)->flush |= flush;
} }
static inline void skb_gro_flush_final_remcsum(struct sk_buff *skb,
struct sk_buff **pp,
int flush,
struct gro_remcsum *grc)
{
if (PTR_ERR(pp) != -EINPROGRESS) {
NAPI_GRO_CB(skb)->flush |= flush;
skb_gro_remcsum_cleanup(skb, grc);
skb->remcsum_offload = 0;
}
}
#else #else
static inline void skb_gro_flush_final(struct sk_buff *skb, struct sk_buff **pp, int flush) static inline void skb_gro_flush_final(struct sk_buff *skb, struct sk_buff **pp, int flush)
{ {
NAPI_GRO_CB(skb)->flush |= flush; NAPI_GRO_CB(skb)->flush |= flush;
} }
static inline void skb_gro_flush_final_remcsum(struct sk_buff *skb,
struct sk_buff **pp,
int flush,
struct gro_remcsum *grc)
{
NAPI_GRO_CB(skb)->flush |= flush;
skb_gro_remcsum_cleanup(skb, grc);
skb->remcsum_offload = 0;
}
#endif #endif
static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev, static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev,
......
...@@ -693,7 +693,7 @@ static struct sk_buff **vlan_gro_receive(struct sk_buff **head, ...@@ -693,7 +693,7 @@ static struct sk_buff **vlan_gro_receive(struct sk_buff **head,
out_unlock: out_unlock:
rcu_read_unlock(); rcu_read_unlock();
out: out:
NAPI_GRO_CB(skb)->flush |= flush; skb_gro_flush_final(skb, pp, flush);
return pp; return pp;
} }
......
...@@ -448,9 +448,7 @@ static struct sk_buff **gue_gro_receive(struct sock *sk, ...@@ -448,9 +448,7 @@ static struct sk_buff **gue_gro_receive(struct sock *sk,
out_unlock: out_unlock:
rcu_read_unlock(); rcu_read_unlock();
out: out:
NAPI_GRO_CB(skb)->flush |= flush; skb_gro_flush_final_remcsum(skb, pp, flush, &grc);
skb_gro_remcsum_cleanup(skb, &grc);
skb->remcsum_offload = 0;
return pp; return pp;
} }
......
...@@ -223,7 +223,7 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head, ...@@ -223,7 +223,7 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head,
out_unlock: out_unlock:
rcu_read_unlock(); rcu_read_unlock();
out: out:
NAPI_GRO_CB(skb)->flush |= flush; skb_gro_flush_final(skb, pp, flush);
return pp; return pp;
} }
......
...@@ -394,7 +394,7 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb, ...@@ -394,7 +394,7 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb,
out_unlock: out_unlock:
rcu_read_unlock(); rcu_read_unlock();
out: out:
NAPI_GRO_CB(skb)->flush |= flush; skb_gro_flush_final(skb, pp, flush);
return pp; return pp;
} }
EXPORT_SYMBOL(udp_gro_receive); EXPORT_SYMBOL(udp_gro_receive);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment