diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 09c444d3b496..d84a09172ddb 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1870,8 +1870,11 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, skb->dev = tun->dev; break; case IFF_TAP: - if (!frags) - skb->protocol = eth_type_trans(skb, tun->dev); + if (frags && !pskb_may_pull(skb, ETH_HLEN)) { + err = -ENOMEM; + goto drop; + } + skb->protocol = eth_type_trans(skb, tun->dev); break; } @@ -1927,8 +1930,11 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, } if (frags) { + u32 headlen; + /* Exercise flow dissector code path. */ - u32 headlen = eth_get_headlen(skb->data, skb_headlen(skb)); + skb_push(skb, ETH_HLEN); + headlen = eth_get_headlen(skb->data, skb_headlen(skb)); if (unlikely(headlen > skb_headlen(skb))) { this_cpu_inc(tun->pcpu_stats->rx_dropped);