Commit 0f0d819a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'xsa448-6.8-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip

Pull xen netback fix from Juergen Gross:
 "Transmit requests in Xen's virtual network protocol can consist of
  multiple parts. While not really useful, except for the initial part
  any of them may be of zero length, i.e. carry no data at all.

  Besides a certain initial portion of the to be transferred data, these
  parts are directly translated into what Linux calls SKB fragments.
  Such converted request parts can, when for a particular SKB they are
  all of length zero, lead to a de-reference of NULL in core networking
  code"

* tag 'xsa448-6.8-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
  xen-netback: don't produce zero-size SKB frags
parents 6613476e c7ec4f2d
...@@ -463,12 +463,25 @@ static void xenvif_get_requests(struct xenvif_queue *queue, ...@@ -463,12 +463,25 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
} }
for (shinfo->nr_frags = 0; nr_slots > 0 && shinfo->nr_frags < MAX_SKB_FRAGS; for (shinfo->nr_frags = 0; nr_slots > 0 && shinfo->nr_frags < MAX_SKB_FRAGS;
shinfo->nr_frags++, gop++, nr_slots--) { nr_slots--) {
if (unlikely(!txp->size)) {
unsigned long flags;
spin_lock_irqsave(&queue->response_lock, flags);
make_tx_response(queue, txp, 0, XEN_NETIF_RSP_OKAY);
push_tx_responses(queue);
spin_unlock_irqrestore(&queue->response_lock, flags);
++txp;
continue;
}
index = pending_index(queue->pending_cons++); index = pending_index(queue->pending_cons++);
pending_idx = queue->pending_ring[index]; pending_idx = queue->pending_ring[index];
xenvif_tx_create_map_op(queue, pending_idx, txp, xenvif_tx_create_map_op(queue, pending_idx, txp,
txp == first ? extra_count : 0, gop); txp == first ? extra_count : 0, gop);
frag_set_pending_idx(&frags[shinfo->nr_frags], pending_idx); frag_set_pending_idx(&frags[shinfo->nr_frags], pending_idx);
++shinfo->nr_frags;
++gop;
if (txp == first) if (txp == first)
txp = txfrags; txp = txfrags;
...@@ -481,20 +494,39 @@ static void xenvif_get_requests(struct xenvif_queue *queue, ...@@ -481,20 +494,39 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
shinfo = skb_shinfo(nskb); shinfo = skb_shinfo(nskb);
frags = shinfo->frags; frags = shinfo->frags;
for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots; for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots; ++txp) {
shinfo->nr_frags++, txp++, gop++) { if (unlikely(!txp->size)) {
unsigned long flags;
spin_lock_irqsave(&queue->response_lock, flags);
make_tx_response(queue, txp, 0,
XEN_NETIF_RSP_OKAY);
push_tx_responses(queue);
spin_unlock_irqrestore(&queue->response_lock,
flags);
continue;
}
index = pending_index(queue->pending_cons++); index = pending_index(queue->pending_cons++);
pending_idx = queue->pending_ring[index]; pending_idx = queue->pending_ring[index];
xenvif_tx_create_map_op(queue, pending_idx, txp, 0, xenvif_tx_create_map_op(queue, pending_idx, txp, 0,
gop); gop);
frag_set_pending_idx(&frags[shinfo->nr_frags], frag_set_pending_idx(&frags[shinfo->nr_frags],
pending_idx); pending_idx);
++shinfo->nr_frags;
++gop;
} }
skb_shinfo(skb)->frag_list = nskb; if (shinfo->nr_frags) {
} else if (nskb) { skb_shinfo(skb)->frag_list = nskb;
nskb = NULL;
}
}
if (nskb) {
/* A frag_list skb was allocated but it is no longer needed /* A frag_list skb was allocated but it is no longer needed
* because enough slots were converted to copy ops above. * because enough slots were converted to copy ops above or some
* were empty.
*/ */
kfree_skb(nskb); kfree_skb(nskb);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment