Patch "net: call rcu_read_lock early in process_backlog" has been added to the 3.10-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
net: call rcu_read_lock early in process_backlog
to the 3.10-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
net-call-rcu_read_lock-early-in-process_backlog.patch
and it can be found in the queue-3.10 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From foo@baz Sat Sep 26 11:20:32 PDT 2015
From: Julian Anastasov <[email protected]>
Date: Thu, 9 Jul 2015 09:59:10 +0300
Subject: net: call rcu_read_lock early in process_backlog
From: Julian Anastasov <[email protected]>
[ Upstream commit 2c17d27c36dcce2b6bf689f41a46b9e909877c21 ]
Incoming packet should be either in backlog queue or in RCU read-side section. Otherwise, the final sequence of flush_backlog() and synchronize_net() may miss packets that can run without device reference:
CPU 1 CPU 2
skb->dev: no reference
process_backlog:__skb_dequeue
process_backlog:local_irq_enableon_each_cpu forflush_backlog => IPI(hardirq): flush_backlog
- packet not found in backlog
CPU delayed ...synchronize_net
- no ongoing RCU
read-side sections
netdev_run_todo,rcu_barrier: no
ongoing callbacks
__netif_receive_skb_core:rcu_read_lock
- too late
free dev
process packet for freed dev
--- net/core/dev.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-)
net/core/dev.c +14 -15
@@ -3443,8 +3443,6 @@ static int __netif_receive_skb_core(stru pt_prev =NULL ; -rcu_read_lock (); - another_round: skb->skb_iif = skb->dev->ifindex;
@@ -3454,7 +3452,7 @@ another_round: skb->protocol == cpu_to_be16(ETH_P_8021AD)) { skb =vlan_untag (skb);if (unlikely (!skb)) - goto unlock; + goto out; }#ifdef CONFIG_NET_CLS_ACT
@@ -3479,7 +3477,7 @@ skip_taps:#ifdef CONFIG_NET_CLS_ACT skb =handle_ing (skb, &pt_prev, &ret, orig_dev);if (!skb) - goto unlock; + goto out; ncls:#endif
@@ -3494,7 +3492,7 @@ ncls:if (vlan_do_receive (&skb)) goto another_round;else if (unlikely (!skb)) - goto unlock; + goto out; } rx_handler =rcu_dereference (skb->dev->rx_handler);
@@ -3506,7 +3504,7 @@ ncls:switch (rx_handler (&skb)) {case RX_HANDLER_CONSUMED : ret =NET_RX_SUCCESS ; - goto unlock; + goto out;case RX_HANDLER_ANOTHER : goto another_round;case RX_HANDLER_EXACT :
@@ -3558,8 +3556,6 @@ drop: ret =NET_RX_DROP ; } -unlock: -rcu_read_unlock (); out:return ret; }
@@ -3606,29 +3602,30 @@ static int __netif_receive_skb(struct sk*/ int netif_receive_skb (struct sk_buff *skb) { +int ret; +net_timestamp_check (netdev_tstamp_prequeue, skb);if (skb_defer_rx_timestamp (skb))return NET_RX_SUCCESS ; +rcu_read_lock (); +#ifdef CONFIG_RPS if (static_key_false (&rps_needed)) {struct rps_dev_flow voidflow, *rflow = &voidflow; -int cpu, ret; - -rcu_read_lock (); - - cpu =get_rps_cpu (skb->dev, skb, &rflow); +int cpu =get_rps_cpu (skb->dev, skb, &rflow);if (cpu >=0 ) { ret =enqueue_to_backlog (skb, cpu, &rflow->last_qtail);rcu_read_unlock ();return ret; } -rcu_read_unlock (); }#endif -return __netif_receive_skb (skb); + ret =__netif_receive_skb (skb); +rcu_read_unlock (); +return ret; }EXPORT_SYMBOL (netif_receive_skb);
@@ -4038,8 +4035,10 @@ static int process_backlog(struct napi_sunsigned int qlen;while ((skb =__skb_dequeue (&sd->process_queue))) { +rcu_read_lock ();local_irq_enable ();__netif_receive_skb (skb); +rcu_read_unlock ();local_irq_disable ();input_queue_head_incr (sd);if (++work >= quota) {
Patches currently in stable-queue which might be from [email protected] are
queue-3.10/net-call-rcu_read_lock-early-in-process_backlog.patch