lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Thu, 26 Feb 2015 22:32:56 -0800 From: Cong Wang <xiyou.wangcong@...il.com> To: netdev@...r.kernel.org Cc: Cong Wang <xiyou.wangcong@...il.com>, Nicolas Dichtel <nicolas.dichtel@...nd.com>, Eric Dumazet <eric.dumazet@...il.com> Subject: [Patch net] netns: avoid allocating idr when dumping info We can allocate the peer netns id when creating the link instead of when dumping the link. This fixes the following kernel warning: =============================== [ INFO: suspicious RCU usage. ] 3.19.0+ #805 Tainted: G W ------------------------------- include/linux/rcupdate.h:538 Illegal context switch in RCU read-side critical section! other info that might help us debug this: rcu_scheduler_active = 1, debug_locks = 0 2 locks held by ip/771: #0: (rtnl_mutex){+.+.+.}, at: [<ffffffff8182b8f4>] netlink_dump+0x21/0x26c #1: (rcu_read_lock){......}, at: [<ffffffff817d785b>] rcu_read_lock+0x0/0x6e stack backtrace: CPU: 3 PID: 771 Comm: ip Tainted: G W 3.19.0+ #805 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 0000000000000001 ffff8800d51e7718 ffffffff81a27457 0000000029e729e6 ffff8800d6108000 ffff8800d51e7748 ffffffff810b539b ffffffff820013dd 00000000000001c8 0000000000000000 ffff8800d7448088 ffff8800d51e7758 Call Trace: [<ffffffff81a27457>] dump_stack+0x4c/0x65 [<ffffffff810b539b>] lockdep_rcu_suspicious+0x107/0x110 [<ffffffff8109796f>] rcu_preempt_sleep_check+0x45/0x47 [<ffffffff8109e457>] ___might_sleep+0x1d/0x1cb [<ffffffff8109e67d>] __might_sleep+0x78/0x80 [<ffffffff814b9b1f>] idr_alloc+0x45/0xd1 [<ffffffff810cb7ab>] ? rcu_read_lock_held+0x3b/0x3d [<ffffffff814b9f9d>] ? idr_for_each+0x53/0x101 [<ffffffff817c1383>] alloc_netid+0x61/0x69 [<ffffffff817c14c3>] __peernet2id+0x79/0x8d [<ffffffff817c1ab7>] peernet2id+0x13/0x1f [<ffffffff817d8673>] rtnl_fill_ifinfo+0xa8d/0xc20 [<ffffffff810b17d9>] ? __lock_is_held+0x39/0x52 [<ffffffff817d894f>] rtnl_dump_ifinfo+0x149/0x213 [<ffffffff8182b9c2>] netlink_dump+0xef/0x26c [<ffffffff8182bcba>] netlink_recvmsg+0x17b/0x2c5 [<ffffffff817b0adc>] __sock_recvmsg+0x4e/0x59 [<ffffffff817b1b40>] sock_recvmsg+0x3f/0x51 [<ffffffff817b1f9a>] ___sys_recvmsg+0xf6/0x1d9 [<ffffffff8115dc67>] ? handle_pte_fault+0x6e1/0xd3d [<ffffffff8100a3a0>] ? native_sched_clock+0x35/0x37 [<ffffffff8109f45b>] ? sched_clock_local+0x12/0x72 [<ffffffff8109f6ac>] ? sched_clock_cpu+0x9e/0xb7 [<ffffffff810cb7ab>] ? rcu_read_lock_held+0x3b/0x3d [<ffffffff811abde8>] ? __fcheck_files+0x4c/0x58 [<ffffffff811ac556>] ? __fget_light+0x2d/0x52 [<ffffffff817b376f>] __sys_recvmsg+0x42/0x60 [<ffffffff817b379f>] SyS_recvmsg+0x12/0x1c Fixes: commit d37512a277dfb2cef ("rtnl: add link netns id to interface messages") Cc: Nicolas Dichtel <nicolas.dichtel@...nd.com> Cc: Eric Dumazet <eric.dumazet@...il.com> Signed-off-by: Cong Wang <xiyou.wangcong@...il.com> --- include/net/net_namespace.h | 14 +++++++++++++- net/core/net_namespace.c | 14 ++------------ net/core/rtnetlink.c | 11 +++++++++-- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 36faf49..25ac2e0 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -27,6 +27,7 @@ #include <net/netns/nftables.h> #include <net/netns/xfrm.h> #include <linux/ns_common.h> +#include <uapi/linux/net_namespace.h> struct user_namespace; struct proc_dir_entry; @@ -291,7 +292,18 @@ static inline struct net *read_pnet(struct net * const *pnet) #define __net_initconst __initconst #endif -int peernet2id(struct net *net, struct net *peer); +int __peernet2id(struct net *net, struct net *peer, bool alloc); + +/* This function returns the id of a peer netns. If no id is assigned, one will + * be allocated and returned. + */ +static inline int peernet2id(struct net *net, struct net *peer) +{ + int id = __peernet2id(net, peer, true); + + return id >= 0 ? id : NETNSA_NSID_NOT_ASSIGNED; +} + struct net *get_net_ns_by_id(struct net *net, int id); struct pernet_operations { diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index cb5290b..9ff2164 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -175,7 +175,7 @@ static int net_eq_idr(int id, void *net, void *peer) return 0; } -static int __peernet2id(struct net *net, struct net *peer, bool alloc) +int __peernet2id(struct net *net, struct net *peer, bool alloc) { int id = idr_for_each(&net->netns_ids, net_eq_idr, peer); @@ -192,17 +192,7 @@ static int __peernet2id(struct net *net, struct net *peer, bool alloc) return -ENOENT; } - -/* This function returns the id of a peer netns. If no id is assigned, one will - * be allocated and returned. - */ -int peernet2id(struct net *net, struct net *peer) -{ - int id = __peernet2id(net, peer, true); - - return id >= 0 ? id : NETNSA_NSID_NOT_ASSIGNED; -} -EXPORT_SYMBOL(peernet2id); +EXPORT_SYMBOL(__peernet2id); struct net *get_net_ns_by_id(struct net *net, int id) { diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 1385de0..a4348ac 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1175,8 +1175,10 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, struct net *link_net = dev->rtnl_link_ops->get_link_net(dev); if (!net_eq(dev_net(dev), link_net)) { - int id = peernet2id(dev_net(dev), link_net); + int id = __peernet2id(dev_net(dev), link_net, false); + if (id < 0) + id = NETNSA_NSID_NOT_ASSIGNED; if (nla_put_s32(skb, IFLA_LINK_NETNSID, id)) goto nla_put_failure; } @@ -2142,7 +2144,12 @@ replay: dev->ifindex = ifm->ifi_index; if (ops->newlink) { - err = ops->newlink(link_net ? : net, dev, tb, data); + struct net *src_net = link_net ?: net; + + if (ops->get_link_net && !net_eq(src_net, dev_net(dev))) + (void)peernet2id(dev_net(dev), src_net); + + err = ops->newlink(src_net, dev, tb, data); /* Drivers should call free_netdev() in ->destructor * and unregister it on failure after registration * so that device could be finally freed in rtnl_unlock. -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists