From: Greg Kroah-Hartman Date: Mon, 17 Dec 2012 20:58:19 +0000 (-0800) Subject: 3.7-stable patches X-Git-Tag: v3.0.58~39 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f64d7fa6766ef3b2528ffd8b66bb9b5330cc083e;p=thirdparty%2Fkernel%2Fstable-queue.git 3.7-stable patches added patches: net-fix-a-race-in-gro_cell_poll.patch --- diff --git a/queue-3.7/net-fix-a-race-in-gro_cell_poll.patch b/queue-3.7/net-fix-a-race-in-gro_cell_poll.patch new file mode 100644 index 00000000000..c365e45ca66 --- /dev/null +++ b/queue-3.7/net-fix-a-race-in-gro_cell_poll.patch @@ -0,0 +1,88 @@ +From 168b60069f773eb662e26ad23e7e8e274ae8cbba Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Mon, 10 Dec 2012 12:32:03 +0000 +Subject: net: fix a race in gro_cell_poll() + + +From: Eric Dumazet + +[ Upstream commit f8e8f97c11d5ff3cc47d85b97c7c35e443dcf490 ] + +Dmitry Kravkov reported packet drops for GRE packets since GRO support +was added. + +There is a race in gro_cell_poll() because we call napi_complete() +without any synchronization with a concurrent gro_cells_receive() + +Once bug was triggered, we queued packets but did not schedule NAPI +poll. + +We can fix this issue using the spinlock protected the napi_skbs queue, +as we have to hold it to perform skb dequeue anyway. + +As we open-code skb_dequeue(), we no longer need to mask IRQS, as both +producer and consumer run under BH context. + +Bug added in commit c9e6bc644e (net: add gro_cells infrastructure) + +Reported-by: Dmitry Kravkov +Signed-off-by: Eric Dumazet +Tested-by: Dmitry Kravkov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/gro_cells.h | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +--- a/include/net/gro_cells.h ++++ b/include/net/gro_cells.h +@@ -17,7 +17,6 @@ struct gro_cells { + + static inline void gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb) + { +- unsigned long flags; + struct gro_cell *cell = gcells->cells; + struct net_device *dev = skb->dev; + +@@ -35,32 +34,37 @@ static inline void gro_cells_receive(str + return; + } + +- spin_lock_irqsave(&cell->napi_skbs.lock, flags); ++ /* We run in BH context */ ++ spin_lock(&cell->napi_skbs.lock); + + __skb_queue_tail(&cell->napi_skbs, skb); + if (skb_queue_len(&cell->napi_skbs) == 1) + napi_schedule(&cell->napi); + +- spin_unlock_irqrestore(&cell->napi_skbs.lock, flags); ++ spin_unlock(&cell->napi_skbs.lock); + } + ++/* called unser BH context */ + static inline int gro_cell_poll(struct napi_struct *napi, int budget) + { + struct gro_cell *cell = container_of(napi, struct gro_cell, napi); + struct sk_buff *skb; + int work_done = 0; + ++ spin_lock(&cell->napi_skbs.lock); + while (work_done < budget) { +- skb = skb_dequeue(&cell->napi_skbs); ++ skb = __skb_dequeue(&cell->napi_skbs); + if (!skb) + break; +- ++ spin_unlock(&cell->napi_skbs.lock); + napi_gro_receive(napi, skb); + work_done++; ++ spin_lock(&cell->napi_skbs.lock); + } + + if (work_done < budget) + napi_complete(napi); ++ spin_unlock(&cell->napi_skbs.lock); + return work_done; + } + diff --git a/queue-3.7/series b/queue-3.7/series new file mode 100644 index 00000000000..f9f610dcbed --- /dev/null +++ b/queue-3.7/series @@ -0,0 +1 @@ +net-fix-a-race-in-gro_cell_poll.patch