Message ID | b97d5f4eaffeeb9d058155bcab63347527261abf.1649341369.git.marcelo.leitner@gmail.com (mailing list archive) |
---|---|
State | Accepted |
Commit | e65812fd22eba32f11abe28cb377cbd64cfb1ba0 |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [net] net/sched: fix initialization order when updating chain 0 head | expand |
Hello: This patch was applied to netdev/net.git (master) by Jakub Kicinski <kuba@kernel.org>: On Thu, 7 Apr 2022 11:29:23 -0300 you wrote: > Currently, when inserting a new filter that needs to sit at the head > of chain 0, it will first update the heads pointer on all devices using > the (shared) block, and only then complete the initialization of the new > element so that it has a "next" element. > > This can lead to a situation that the chain 0 head is propagated to > another CPU before the "next" initialization is done. When this race > condition is triggered, packets being matched on that CPU will simply > miss all other filters, and will flow through the stack as if there were > no other filters installed. If the system is using OVS + TC, such > packets will get handled by vswitchd via upcall, which results in much > higher latency and reordering. For other applications it may result in > packet drops. > > [...] Here is the summary with links: - [net] net/sched: fix initialization order when updating chain 0 head https://git.kernel.org/netdev/net/c/e65812fd22eb You are awesome, thank you!
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 2957f8f5cea759315463d5e61fa1db745746e6f7..f0699f39afdb082067e581a5ff1ce217351c4a19 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -1672,10 +1672,10 @@ static int tcf_chain_tp_insert(struct tcf_chain *chain, if (chain->flushing) return -EAGAIN; + RCU_INIT_POINTER(tp->next, tcf_chain_tp_prev(chain, chain_info)); if (*chain_info->pprev == chain->filter_chain) tcf_chain0_head_change(chain, tp); tcf_proto_get(tp); - RCU_INIT_POINTER(tp->next, tcf_chain_tp_prev(chain, chain_info)); rcu_assign_pointer(*chain_info->pprev, tp); return 0;