diff options
author | Paul Moore <paul@paul-moore.com> | 2016-10-21 21:49:14 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-10-22 16:16:29 -0400 |
commit | 2a73306b6096fafd5c2ae06ded1f92bbacb39df2 (patch) | |
tree | 11c4861c68b5c93cdd6b039a057484e0d2516269 /net/core | |
parent | 8651be8f14a12d24f203f283601d9b0418c389ff (diff) |
netns: revert "netns: avoid disabling irq for netns id"
This reverts commit bc51dddf98c9 ("netns: avoid disabling irq for
netns id") as it was found to cause problems with systems running
SELinux/audit, see the mailing list thread below:
* http://marc.info/?t=147694653900002&r=1&w=2
Eventually we should be able to reintroduce this code once we have
rewritten the audit multicast code to queue messages much the same
way we do for unicast messages. A tracking issue for this can be
found below:
* https://github.com/linux-audit/audit-kernel/issues/23
Reported-by: Stephen Smalley <sds@tycho.nsa.gov>
Reported-by: Elad Raz <e@eladraz.com>
Cc: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/net_namespace.c | 35 |
1 files changed, 20 insertions, 15 deletions
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 989434f36f96..f61c0e02a413 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
@@ -215,13 +215,14 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id); | |||
215 | */ | 215 | */ |
216 | int peernet2id_alloc(struct net *net, struct net *peer) | 216 | int peernet2id_alloc(struct net *net, struct net *peer) |
217 | { | 217 | { |
218 | unsigned long flags; | ||
218 | bool alloc; | 219 | bool alloc; |
219 | int id; | 220 | int id; |
220 | 221 | ||
221 | spin_lock_bh(&net->nsid_lock); | 222 | spin_lock_irqsave(&net->nsid_lock, flags); |
222 | alloc = atomic_read(&peer->count) == 0 ? false : true; | 223 | alloc = atomic_read(&peer->count) == 0 ? false : true; |
223 | id = __peernet2id_alloc(net, peer, &alloc); | 224 | id = __peernet2id_alloc(net, peer, &alloc); |
224 | spin_unlock_bh(&net->nsid_lock); | 225 | spin_unlock_irqrestore(&net->nsid_lock, flags); |
225 | if (alloc && id >= 0) | 226 | if (alloc && id >= 0) |
226 | rtnl_net_notifyid(net, RTM_NEWNSID, id); | 227 | rtnl_net_notifyid(net, RTM_NEWNSID, id); |
227 | return id; | 228 | return id; |
@@ -230,11 +231,12 @@ int peernet2id_alloc(struct net *net, struct net *peer) | |||
230 | /* This function returns, if assigned, the id of a peer netns. */ | 231 | /* This function returns, if assigned, the id of a peer netns. */ |
231 | int peernet2id(struct net *net, struct net *peer) | 232 | int peernet2id(struct net *net, struct net *peer) |
232 | { | 233 | { |
234 | unsigned long flags; | ||
233 | int id; | 235 | int id; |
234 | 236 | ||
235 | spin_lock_bh(&net->nsid_lock); | 237 | spin_lock_irqsave(&net->nsid_lock, flags); |
236 | id = __peernet2id(net, peer); | 238 | id = __peernet2id(net, peer); |
237 | spin_unlock_bh(&net->nsid_lock); | 239 | spin_unlock_irqrestore(&net->nsid_lock, flags); |
238 | return id; | 240 | return id; |
239 | } | 241 | } |
240 | EXPORT_SYMBOL(peernet2id); | 242 | EXPORT_SYMBOL(peernet2id); |
@@ -249,17 +251,18 @@ bool peernet_has_id(struct net *net, struct net *peer) | |||
249 | 251 | ||
250 | struct net *get_net_ns_by_id(struct net *net, int id) | 252 | struct net *get_net_ns_by_id(struct net *net, int id) |
251 | { | 253 | { |
254 | unsigned long flags; | ||
252 | struct net *peer; | 255 | struct net *peer; |
253 | 256 | ||
254 | if (id < 0) | 257 | if (id < 0) |
255 | return NULL; | 258 | return NULL; |
256 | 259 | ||
257 | rcu_read_lock(); | 260 | rcu_read_lock(); |
258 | spin_lock_bh(&net->nsid_lock); | 261 | spin_lock_irqsave(&net->nsid_lock, flags); |
259 | peer = idr_find(&net->netns_ids, id); | 262 | peer = idr_find(&net->netns_ids, id); |
260 | if (peer) | 263 | if (peer) |
261 | get_net(peer); | 264 | get_net(peer); |
262 | spin_unlock_bh(&net->nsid_lock); | 265 | spin_unlock_irqrestore(&net->nsid_lock, flags); |
263 | rcu_read_unlock(); | 266 | rcu_read_unlock(); |
264 | 267 | ||
265 | return peer; | 268 | return peer; |
@@ -422,17 +425,17 @@ static void cleanup_net(struct work_struct *work) | |||
422 | for_each_net(tmp) { | 425 | for_each_net(tmp) { |
423 | int id; | 426 | int id; |
424 | 427 | ||
425 | spin_lock_bh(&tmp->nsid_lock); | 428 | spin_lock_irq(&tmp->nsid_lock); |
426 | id = __peernet2id(tmp, net); | 429 | id = __peernet2id(tmp, net); |
427 | if (id >= 0) | 430 | if (id >= 0) |
428 | idr_remove(&tmp->netns_ids, id); | 431 | idr_remove(&tmp->netns_ids, id); |
429 | spin_unlock_bh(&tmp->nsid_lock); | 432 | spin_unlock_irq(&tmp->nsid_lock); |
430 | if (id >= 0) | 433 | if (id >= 0) |
431 | rtnl_net_notifyid(tmp, RTM_DELNSID, id); | 434 | rtnl_net_notifyid(tmp, RTM_DELNSID, id); |
432 | } | 435 | } |
433 | spin_lock_bh(&net->nsid_lock); | 436 | spin_lock_irq(&net->nsid_lock); |
434 | idr_destroy(&net->netns_ids); | 437 | idr_destroy(&net->netns_ids); |
435 | spin_unlock_bh(&net->nsid_lock); | 438 | spin_unlock_irq(&net->nsid_lock); |
436 | 439 | ||
437 | } | 440 | } |
438 | rtnl_unlock(); | 441 | rtnl_unlock(); |
@@ -561,6 +564,7 @@ static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
561 | { | 564 | { |
562 | struct net *net = sock_net(skb->sk); | 565 | struct net *net = sock_net(skb->sk); |
563 | struct nlattr *tb[NETNSA_MAX + 1]; | 566 | struct nlattr *tb[NETNSA_MAX + 1]; |
567 | unsigned long flags; | ||
564 | struct net *peer; | 568 | struct net *peer; |
565 | int nsid, err; | 569 | int nsid, err; |
566 | 570 | ||
@@ -581,15 +585,15 @@ static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
581 | if (IS_ERR(peer)) | 585 | if (IS_ERR(peer)) |
582 | return PTR_ERR(peer); | 586 | return PTR_ERR(peer); |
583 | 587 | ||
584 | spin_lock_bh(&net->nsid_lock); | 588 | spin_lock_irqsave(&net->nsid_lock, flags); |
585 | if (__peernet2id(net, peer) >= 0) { | 589 | if (__peernet2id(net, peer) >= 0) { |
586 | spin_unlock_bh(&net->nsid_lock); | 590 | spin_unlock_irqrestore(&net->nsid_lock, flags); |
587 | err = -EEXIST; | 591 | err = -EEXIST; |
588 | goto out; | 592 | goto out; |
589 | } | 593 | } |
590 | 594 | ||
591 | err = alloc_netid(net, peer, nsid); | 595 | err = alloc_netid(net, peer, nsid); |
592 | spin_unlock_bh(&net->nsid_lock); | 596 | spin_unlock_irqrestore(&net->nsid_lock, flags); |
593 | if (err >= 0) { | 597 | if (err >= 0) { |
594 | rtnl_net_notifyid(net, RTM_NEWNSID, err); | 598 | rtnl_net_notifyid(net, RTM_NEWNSID, err); |
595 | err = 0; | 599 | err = 0; |
@@ -711,10 +715,11 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) | |||
711 | .idx = 0, | 715 | .idx = 0, |
712 | .s_idx = cb->args[0], | 716 | .s_idx = cb->args[0], |
713 | }; | 717 | }; |
718 | unsigned long flags; | ||
714 | 719 | ||
715 | spin_lock_bh(&net->nsid_lock); | 720 | spin_lock_irqsave(&net->nsid_lock, flags); |
716 | idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb); | 721 | idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb); |
717 | spin_unlock_bh(&net->nsid_lock); | 722 | spin_unlock_irqrestore(&net->nsid_lock, flags); |
718 | 723 | ||
719 | cb->args[0] = net_cb.idx; | 724 | cb->args[0] = net_cb.idx; |
720 | return skb->len; | 725 | return skb->len; |