Skip to content

Commit 492b67e

Browse files
LorenzoBianconidavem330
authored andcommitted
net: ip_gre: fix possible use-after-free in erspan_rcv
erspan tunnels run __iptunnel_pull_header on received skbs to remove gre and erspan headers. This can determine a possible use-after-free accessing pkt_md pointer in erspan_rcv since the packet will be 'uncloned' running pskb_expand_head if it is a cloned gso skb (e.g if the packet has been sent though a veth device). Fix it resetting pkt_md pointer after __iptunnel_pull_header Fixes: 1d7e2ed ("net: erspan: refactor existing erspan code") Signed-off-by: Lorenzo Bianconi <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b75bb8a commit 492b67e

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

net/ipv4/ip_gre.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,6 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
259259
struct net *net = dev_net(skb->dev);
260260
struct metadata_dst *tun_dst = NULL;
261261
struct erspan_base_hdr *ershdr;
262-
struct erspan_metadata *pkt_md;
263262
struct ip_tunnel_net *itn;
264263
struct ip_tunnel *tunnel;
265264
const struct iphdr *iph;
@@ -282,18 +281,16 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
282281
if (unlikely(!pskb_may_pull(skb, len)))
283282
return PACKET_REJECT;
284283

285-
ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
286-
pkt_md = (struct erspan_metadata *)(ershdr + 1);
287-
288284
if (__iptunnel_pull_header(skb,
289285
len,
290286
htons(ETH_P_TEB),
291287
false, false) < 0)
292288
goto drop;
293289

294290
if (tunnel->collect_md) {
291+
struct erspan_metadata *pkt_md, *md;
295292
struct ip_tunnel_info *info;
296-
struct erspan_metadata *md;
293+
unsigned char *gh;
297294
__be64 tun_id;
298295
__be16 flags;
299296

@@ -306,6 +303,14 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
306303
if (!tun_dst)
307304
return PACKET_REJECT;
308305

306+
/* skb can be uncloned in __iptunnel_pull_header, so
307+
* old pkt_md is no longer valid and we need to reset
308+
* it
309+
*/
310+
gh = skb_network_header(skb) +
311+
skb_network_header_len(skb);
312+
pkt_md = (struct erspan_metadata *)(gh + gre_hdr_len +
313+
sizeof(*ershdr));
309314
md = ip_tunnel_info_opts(&tun_dst->u.tun_info);
310315
md->version = ver;
311316
md2 = &md->u.md2;

0 commit comments

Comments
 (0)