Skip to contentSkip to conversation

Patch "net: sched: fix call_rcu() race on classifier module unloads" has been added to the 4.0-stable tree

PATCH [email protected] 1 participant 1 message Jun 13, 2015

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

net: sched: fix call_rcu() race on classifier module unloads

to the 4.0-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-sched-fix-call_rcu-race-on-classifier-module-unloads.patch
and it can be found in the queue-4.0 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 Jun 13 09:48:35 PDT 2015

From: Daniel Borkmann <[email protected]>
Date: Wed, 20 May 2015 17:13:33 +0200
Subject: net: sched: fix call_rcu() race on classifier module unloads

From: Daniel Borkmann <[email protected]>

[ Upstream commit c78e1746d3ad7d548bdf3fe491898cc453911a49 ]

Vijay reported that a loop as simple as ...

while true; do
tc qdisc add dev foo root handle 1: prio
tc filter add dev foo parent 1: u32 match u32 0 0 flowid 1 tc qdisc del dev foo root
rmmod cls_u32
done

... will panic the kernel. Moreover, he bisected the change apparently introducing it to 78fd1d0ab072 ("netlink: Re-add locking to netlink_lookup() and seq walker").

The removal of synchronize_net() from the netlink socket triggering the qdisc to be removed, seems to have uncovered an RCU resp. module reference count race from the tc API. Given that RCU conversion was done after e341694e3eb5 ("netlink:
Convert netlink_lookup() to use RCU protected hash table") which added the synchronize_net() originally, occasion of hitting the bug was less likely (not impossible though):

When qdiscs that i) support attaching classifiers and, ii) have at least one of them attached, get deleted, they invoke tcf_destroy_chain(), and thus call into ->destroy() handler from a classifier module.

After RCU conversion, all classifier that have an internal prio list, unlink them and initiate freeing via call_rcu() deferral.

Meanhile, tcf_destroy() releases already reference to the tp->ops->owner module before the queued RCU callback handler has been invoked.

Subsequent rmmod on the classifier module is then not prevented since all module references are already dropped.

By the time, the kernel invokes the RCU callback handler from the module, that function address is then invalid.

One way to fix it would be to add an rcu_barrier() to unregister_tcf_proto_ops() to wait for all pending call_rcu()s to complete.

synchronize_rcu() is not appropriate as under heavy RCU callback load, registered call_rcu()s could be deferred longer than a grace period. In case we don't have any pending call_rcu()s, the barrier is allowed to return immediately.

Since we came here via unregister_tcf_proto_ops(), there are no users of a given classifier anymore. Further nested call_rcu()s pointing into the module space are not being done anywhere.

Only cls_bpf_delete_prog() may schedule a work item, to unlock pages eventually, but that is not in the range/context of cls_bpf anymore.

Fixes 25d8c0d55f24 ("net: rcu-ify tcf_proto")
Fixes 9888faefe132 ("net: sched: cls_basic use RCU")
Cc John Fastabend <[email protected]>
Cc Eric Dumazet <[email protected]>
Cc Thomas Graf <[email protected]>
Cc Jamal Hadi Salim <[email protected]>
Cc Alexei Starovoitov <[email protected]>
---
 net/sched/cls_api.c |    5 +++++
 1 file changed, 5 insertions(+)
net/sched/cls_api.c +5 -0
@@ -81,6 +81,11 @@ int unregister_tcf_proto_ops(struct tcf_
 	struct tcf_proto_ops *t;
 	int rc = -ENOENT;
 
+	/* Wait for outstanding call_rcu()s, if any, from a
+	 * tcf_proto_ops's destroy() handler.
+	 */
+	rcu_barrier();
+
 	write_lock(&cls_mod_lock);
 	list_for_each_entry(t, &tcf_proto_base, head) {
 		if (t == ops) {

Patches currently in stable-queue which might be from [email protected] are

queue-4.0/x86-bpf_jit-fix-compilation-of-large-bpf-programs.patch queue-4.0/sctp-fix-mangled-ipv4-addresses-on-a-ipv6-listening-socket.patch queue-4.0/net-sched-fix-call_rcu-race-on-classifier-module-unloads.patch queue-4.0/tcp-fix-child-sockets-to-use-system-default-congestion-control-if-not-set.patch