Skip to content

Commit 2dce224

Browse files
Guillaume Naultdavem330
authored andcommitted
netns: protect netns ID lookups with RCU
__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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4905294 commit 2dce224

File tree

1 file changed

+7
-15
lines changed

1 file changed

+7
-15
lines changed

net/core/net_namespace.c

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ static int net_eq_idr(int id, void *net, void *peer)
211211
return 0;
212212
}
213213

214-
/* Should be called with nsid_lock held. */
214+
/* Must be called from RCU-critical section or with nsid_lock held */
215215
static int __peernet2id(const struct net *net, struct net *peer)
216216
{
217217
int id = idr_for_each(&net->netns_ids, net_eq_idr, peer);
@@ -272,9 +272,10 @@ int peernet2id(struct net *net, struct net *peer)
272272
{
273273
int id;
274274

275-
spin_lock_bh(&net->nsid_lock);
275+
rcu_read_lock();
276276
id = __peernet2id(net, peer);
277-
spin_unlock_bh(&net->nsid_lock);
277+
rcu_read_unlock();
278+
278279
return id;
279280
}
280281
EXPORT_SYMBOL(peernet2id);
@@ -941,6 +942,7 @@ struct rtnl_net_dump_cb {
941942
int s_idx;
942943
};
943944

945+
/* Runs in RCU-critical section. */
944946
static int rtnl_net_dumpid_one(int id, void *peer, void *data)
945947
{
946948
struct rtnl_net_dump_cb *net_cb = (struct rtnl_net_dump_cb *)data;
@@ -1025,19 +1027,9 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
10251027
goto end;
10261028
}
10271029

1028-
spin_lock_bh(&net_cb.tgt_net->nsid_lock);
1029-
if (net_cb.fillargs.add_ref &&
1030-
!net_eq(net_cb.ref_net, net_cb.tgt_net) &&
1031-
!spin_trylock_bh(&net_cb.ref_net->nsid_lock)) {
1032-
spin_unlock_bh(&net_cb.tgt_net->nsid_lock);
1033-
err = -EAGAIN;
1034-
goto end;
1035-
}
1030+
rcu_read_lock();
10361031
idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb);
1037-
if (net_cb.fillargs.add_ref &&
1038-
!net_eq(net_cb.ref_net, net_cb.tgt_net))
1039-
spin_unlock_bh(&net_cb.ref_net->nsid_lock);
1040-
spin_unlock_bh(&net_cb.tgt_net->nsid_lock);
1032+
rcu_read_unlock();
10411033

10421034
cb->args[0] = net_cb.idx;
10431035
end:

0 commit comments

Comments
 (0)