|
@@ -3530,6 +3530,25 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
|
|
|
int pos;
|
|
int pos;
|
|
|
int dummy;
|
|
int dummy;
|
|
|
|
|
|
|
|
|
|
+ if (list_skb && !list_skb->head_frag && skb_headlen(list_skb) &&
|
|
|
|
|
+ (skb_shinfo(head_skb)->gso_type & SKB_GSO_DODGY)) {
|
|
|
|
|
+ /* gso_size is untrusted, and we have a frag_list with a linear
|
|
|
|
|
+ * non head_frag head.
|
|
|
|
|
+ *
|
|
|
|
|
+ * (we assume checking the first list_skb member suffices;
|
|
|
|
|
+ * i.e if either of the list_skb members have non head_frag
|
|
|
|
|
+ * head, then the first one has too).
|
|
|
|
|
+ *
|
|
|
|
|
+ * If head_skb's headlen does not fit requested gso_size, it
|
|
|
|
|
+ * means that the frag_list members do NOT terminate on exact
|
|
|
|
|
+ * gso_size boundaries. Hence we cannot perform skb_frag_t page
|
|
|
|
|
+ * sharing. Therefore we must fallback to copying the frag_list
|
|
|
|
|
+ * skbs; we do so by disabling SG.
|
|
|
|
|
+ */
|
|
|
|
|
+ if (mss != GSO_BY_FRAGS && mss != skb_headlen(head_skb))
|
|
|
|
|
+ features &= ~NETIF_F_SG;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
__skb_push(head_skb, doffset);
|
|
__skb_push(head_skb, doffset);
|
|
|
proto = skb_network_protocol(head_skb, &dummy);
|
|
proto = skb_network_protocol(head_skb, &dummy);
|
|
|
if (unlikely(!proto))
|
|
if (unlikely(!proto))
|