if (ihl < sizeof(*iph))
                goto out;
 
+       proto = iph->protocol;
+
+       /* Warning: after this point, iph might be no longer valid */
        if (unlikely(!pskb_may_pull(skb, ihl)))
                goto out;
-
        __skb_pull(skb, ihl);
+
        skb_reset_transport_header(skb);
-       iph = ip_hdr(skb);
-       proto = iph->protocol;
        err = -EPROTONOSUPPORT;
 
-       rcu_read_lock();
        ops = rcu_dereference(inet_offloads[proto]);
        if (likely(ops && ops->callbacks.gso_send_check))
                err = ops->callbacks.gso_send_check(skb);
-       rcu_read_unlock();
 
 out:
        return err;
        if (ihl < sizeof(*iph))
                goto out;
 
+       id = ntohs(iph->id);
+       proto = iph->protocol;
+
+       /* Warning: after this point, iph might be no longer valid */
        if (unlikely(!pskb_may_pull(skb, ihl)))
                goto out;
+       __skb_pull(skb, ihl);
 
        tunnel = !!skb->encapsulation;
 
-       __skb_pull(skb, ihl);
        skb_reset_transport_header(skb);
-       iph = ip_hdr(skb);
-       id = ntohs(iph->id);
-       proto = iph->protocol;
+
        segs = ERR_PTR(-EPROTONOSUPPORT);
 
-       rcu_read_lock();
        ops = rcu_dereference(inet_offloads[proto]);
        if (likely(ops && ops->callbacks.gso_segment))
                segs = ops->callbacks.gso_segment(skb, features);
-       rcu_read_unlock();
 
        if (IS_ERR_OR_NULL(segs))
                goto out;
                        iph->id = htons(id++);
                }
                iph->tot_len = htons(skb->len - skb->mac_len);
-               iph->check = 0;
-               iph->check = ip_fast_csum(skb_network_header(skb), iph->ihl);
+               ip_send_check(iph);
        } while ((skb = skb->next));
 
 out: