From: Greg Kroah-Hartman Date: Mon, 13 Sep 2021 08:43:03 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v5.4.146~39 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=286f4e3d58aa536e3edd1833ac7d2149b45d4fa7;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: netns-protect-netns-id-lookups-with-rcu.patch --- diff --git a/queue-4.14/netns-protect-netns-id-lookups-with-rcu.patch b/queue-4.14/netns-protect-netns-id-lookups-with-rcu.patch new file mode 100644 index 00000000000..caa4d028364 --- /dev/null +++ b/queue-4.14/netns-protect-netns-id-lookups-with-rcu.patch @@ -0,0 +1,84 @@ +From 2dce224f469f060b9998a5a869151ef83c08ce77 Mon Sep 17 00:00:00 2001 +From: Guillaume Nault +Date: Mon, 13 Jan 2020 22:39:22 +0100 +Subject: netns: protect netns ID lookups with RCU + +From: Guillaume Nault + +commit 2dce224f469f060b9998a5a869151ef83c08ce77 upstream. + +__peernet2id() can be protected by RCU as it only calls idr_for_each(), +which is RCU-safe, and never modifies the nsid table. + +rtnl_net_dumpid() can also do lockless lookups. It does two nested +idr_for_each() calls on nsid tables (one direct call and one indirect +call because of rtnl_net_dumpid_one() calling __peernet2id()). The +netnsid tables are never updated. Therefore it is safe to not take the +nsid_lock and run within an RCU-critical section instead. + +Signed-off-by: Guillaume Nault +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: HÃ¥kon Bugge + +--- + net/core/net_namespace.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +--- a/net/core/net_namespace.c ++++ b/net/core/net_namespace.c +@@ -181,9 +181,9 @@ static int net_eq_idr(int id, void *net, + return 0; + } + +-/* Should be called with nsid_lock held. If a new id is assigned, the bool alloc +- * is set to true, thus the caller knows that the new id must be notified via +- * rtnl. ++/* Must be called from RCU-critical section or with nsid_lock held. If ++ * a new id is assigned, the bool alloc is set to true, thus the ++ * caller knows that the new id must be notified via rtnl. + */ + static int __peernet2id_alloc(struct net *net, struct net *peer, bool *alloc) + { +@@ -207,7 +207,7 @@ static int __peernet2id_alloc(struct net + return NETNSA_NSID_NOT_ASSIGNED; + } + +-/* should be called with nsid_lock held */ ++/* Must be called from RCU-critical section or with nsid_lock held */ + static int __peernet2id(struct net *net, struct net *peer) + { + bool no = false; +@@ -240,9 +240,10 @@ int peernet2id(struct net *net, struct n + { + int id; + +- spin_lock_bh(&net->nsid_lock); ++ rcu_read_lock(); + id = __peernet2id(net, peer); +- spin_unlock_bh(&net->nsid_lock); ++ rcu_read_unlock(); ++ + return id; + } + EXPORT_SYMBOL(peernet2id); +@@ -761,6 +762,7 @@ struct rtnl_net_dump_cb { + int s_idx; + }; + ++/* Runs in RCU-critical section. */ + static int rtnl_net_dumpid_one(int id, void *peer, void *data) + { + struct rtnl_net_dump_cb *net_cb = (struct rtnl_net_dump_cb *)data; +@@ -791,9 +793,9 @@ static int rtnl_net_dumpid(struct sk_buf + .s_idx = cb->args[0], + }; + +- spin_lock_bh(&net->nsid_lock); ++ rcu_read_lock(); + idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb); +- spin_unlock_bh(&net->nsid_lock); ++ rcu_read_unlock(); + + cb->args[0] = net_cb.idx; + return skb->len; diff --git a/queue-4.14/series b/queue-4.14/series index af9d713844a..d98c0fb2566 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -89,3 +89,4 @@ bcma-fix-memory-leak-for-internally-handled-cores.patch ipv4-make-exception-cache-less-predictible.patch net-sched-fix-qdisc_rate_table-refcount-leak-when-ge.patch net-qualcomm-fix-qca7000-checksum-handling.patch +netns-protect-netns-id-lookups-with-rcu.patch