aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Moore <paul@paul-moore.com>2016-11-29 16:57:48 -0500
committerPaul Moore <paul@paul-moore.com>2016-12-14 13:06:04 -0500
commitfba143c66abb81307a450679f38ab953fe96a413 (patch)
treec9933c76c704f6751b10b662fc9c8ec4a1682529
parenta09cfa470817ac086cf68418da13a2b91c2744ef (diff)
netns: avoid disabling irq for netns id
Bring back commit bc51dddf98c9 ("netns: avoid disabling irq for netns id") now that we've fixed some audit multicast issues that caused problems with original attempt. Additional information, and history, can be found in the links below: * https://github.com/linux-audit/audit-kernel/issues/22 * https://github.com/linux-audit/audit-kernel/issues/23 Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
-rw-r--r--net/core/net_namespace.c35
1 files changed, 15 insertions, 20 deletions
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 2c2eb1b629b1..10608dd1489f 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -213,14 +213,13 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id);
213 */ 213 */
214int peernet2id_alloc(struct net *net, struct net *peer) 214int peernet2id_alloc(struct net *net, struct net *peer)
215{ 215{
216 unsigned long flags;
217 bool alloc; 216 bool alloc;
218 int id; 217 int id;
219 218
220 spin_lock_irqsave(&net->nsid_lock, flags); 219 spin_lock_bh(&net->nsid_lock);
221 alloc = atomic_read(&peer->count) == 0 ? false : true; 220 alloc = atomic_read(&peer->count) == 0 ? false : true;
222 id = __peernet2id_alloc(net, peer, &alloc); 221 id = __peernet2id_alloc(net, peer, &alloc);
223 spin_unlock_irqrestore(&net->nsid_lock, flags); 222 spin_unlock_bh(&net->nsid_lock);
224 if (alloc && id >= 0) 223 if (alloc && id >= 0)
225 rtnl_net_notifyid(net, RTM_NEWNSID, id); 224 rtnl_net_notifyid(net, RTM_NEWNSID, id);
226 return id; 225 return id;
@@ -230,12 +229,11 @@ EXPORT_SYMBOL(peernet2id_alloc);
230/* This function returns, if assigned, the id of a peer netns. */ 229/* This function returns, if assigned, the id of a peer netns. */
231int peernet2id(struct net *net, struct net *peer) 230int peernet2id(struct net *net, struct net *peer)
232{ 231{
233 unsigned long flags;
234 int id; 232 int id;
235 233
236 spin_lock_irqsave(&net->nsid_lock, flags); 234 spin_lock_bh(&net->nsid_lock);
237 id = __peernet2id(net, peer); 235 id = __peernet2id(net, peer);
238 spin_unlock_irqrestore(&net->nsid_lock, flags); 236 spin_unlock_bh(&net->nsid_lock);
239 return id; 237 return id;
240} 238}
241 239
@@ -249,18 +247,17 @@ bool peernet_has_id(struct net *net, struct net *peer)
249 247
250struct net *get_net_ns_by_id(struct net *net, int id) 248struct net *get_net_ns_by_id(struct net *net, int id)
251{ 249{
252 unsigned long flags;
253 struct net *peer; 250 struct net *peer;
254 251
255 if (id < 0) 252 if (id < 0)
256 return NULL; 253 return NULL;
257 254
258 rcu_read_lock(); 255 rcu_read_lock();
259 spin_lock_irqsave(&net->nsid_lock, flags); 256 spin_lock_bh(&net->nsid_lock);
260 peer = idr_find(&net->netns_ids, id); 257 peer = idr_find(&net->netns_ids, id);
261 if (peer) 258 if (peer)
262 get_net(peer); 259 get_net(peer);
263 spin_unlock_irqrestore(&net->nsid_lock, flags); 260 spin_unlock_bh(&net->nsid_lock);
264 rcu_read_unlock(); 261 rcu_read_unlock();
265 262
266 return peer; 263 return peer;
@@ -404,17 +401,17 @@ static void cleanup_net(struct work_struct *work)
404 for_each_net(tmp) { 401 for_each_net(tmp) {
405 int id; 402 int id;
406 403
407 spin_lock_irq(&tmp->nsid_lock); 404 spin_lock_bh(&tmp->nsid_lock);
408 id = __peernet2id(tmp, net); 405 id = __peernet2id(tmp, net);
409 if (id >= 0) 406 if (id >= 0)
410 idr_remove(&tmp->netns_ids, id); 407 idr_remove(&tmp->netns_ids, id);
411 spin_unlock_irq(&tmp->nsid_lock); 408 spin_unlock_bh(&tmp->nsid_lock);
412 if (id >= 0) 409 if (id >= 0)
413 rtnl_net_notifyid(tmp, RTM_DELNSID, id); 410 rtnl_net_notifyid(tmp, RTM_DELNSID, id);
414 } 411 }
415 spin_lock_irq(&net->nsid_lock); 412 spin_lock_bh(&net->nsid_lock);
416 idr_destroy(&net->netns_ids); 413 idr_destroy(&net->netns_ids);
417 spin_unlock_irq(&net->nsid_lock); 414 spin_unlock_bh(&net->nsid_lock);
418 415
419 } 416 }
420 rtnl_unlock(); 417 rtnl_unlock();
@@ -542,7 +539,6 @@ static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh)
542{ 539{
543 struct net *net = sock_net(skb->sk); 540 struct net *net = sock_net(skb->sk);
544 struct nlattr *tb[NETNSA_MAX + 1]; 541 struct nlattr *tb[NETNSA_MAX + 1];
545 unsigned long flags;
546 struct net *peer; 542 struct net *peer;
547 int nsid, err; 543 int nsid, err;
548 544
@@ -563,15 +559,15 @@ static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh)
563 if (IS_ERR(peer)) 559 if (IS_ERR(peer))
564 return PTR_ERR(peer); 560 return PTR_ERR(peer);
565 561
566 spin_lock_irqsave(&net->nsid_lock, flags); 562 spin_lock_bh(&net->nsid_lock);
567 if (__peernet2id(net, peer) >= 0) { 563 if (__peernet2id(net, peer) >= 0) {
568 spin_unlock_irqrestore(&net->nsid_lock, flags); 564 spin_unlock_bh(&net->nsid_lock);
569 err = -EEXIST; 565 err = -EEXIST;
570 goto out; 566 goto out;
571 } 567 }
572 568
573 err = alloc_netid(net, peer, nsid); 569 err = alloc_netid(net, peer, nsid);
574 spin_unlock_irqrestore(&net->nsid_lock, flags); 570 spin_unlock_bh(&net->nsid_lock);
575 if (err >= 0) { 571 if (err >= 0) {
576 rtnl_net_notifyid(net, RTM_NEWNSID, err); 572 rtnl_net_notifyid(net, RTM_NEWNSID, err);
577 err = 0; 573 err = 0;
@@ -693,11 +689,10 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
693 .idx = 0, 689 .idx = 0,
694 .s_idx = cb->args[0], 690 .s_idx = cb->args[0],
695 }; 691 };
696 unsigned long flags;
697 692
698 spin_lock_irqsave(&net->nsid_lock, flags); 693 spin_lock_bh(&net->nsid_lock);
699 idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb); 694 idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb);
700 spin_unlock_irqrestore(&net->nsid_lock, flags); 695 spin_unlock_bh(&net->nsid_lock);
701 696
702 cb->args[0] = net_cb.idx; 697 cb->args[0] = net_cb.idx;
703 return skb->len; 698 return skb->len;