skbuff: skb_segment: orphan frags before copying

skb_segment copies frags around, so we need
to copy them carefully to avoid accessing
user memory after reporting completion to userspace
through a callback.

skb_segment doesn't normally happen on datapath:
TSO needs to be disabled - so disabling zero copy
in this case does not look like a big deal.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
static void skb_release_data(struct sk_buff *skb)
{
	if (!skb->cloned ||
	    !atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1,
			       &skb_shinfo(skb)->dataref)) {
		if (skb_shinfo(skb)->nr_frags) {
			int i;
			for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
				skb_frag_unref(skb, i);
		}

		/*
		 * If skb buf is from userspace, we need to notify the caller
		 * the lower device DMA has done;
		 */
		if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) {
			struct ubuf_info *uarg;

			uarg = skb_shinfo(skb)->destructor_arg;
			if (uarg->callback)
				uarg->callback(uarg, true);
		}

		if (skb_has_frag_list(skb))
			skb_drop_fraglist(skb);

		skb_free_head(skb);
	}
}

static void skb_release_data(struct sk_buff *skb)
{
	if (!skb->cloned ||
	    !atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1,
			       &skb_shinfo(skb)->dataref)) {
		if (skb_shinfo(skb)->nr_frags) {
			int i;
			for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
				skb_frag_unref(skb, i);
		}

		/*
		 * If skb buf is from userspace, we need to notify the caller
		 * the lower device DMA has done;
		 */
		if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) {
			struct ubuf_info *uarg;

			uarg = skb_shinfo(skb)->destructor_arg;
			if (uarg->callback)
				uarg->callback(uarg, true);
		}

		if (skb_has_frag_list(skb))
			skb_drop_fraglist(skb);

		skb_free_head(skb);
	}
}
