From: Eric Dumazet <eric.dumazet@gmail.com>
To: "David S . Miller" <davem@davemloft.net>,
Jakub Kicinski <kuba@kernel.org>
Cc: netdev <netdev@vger.kernel.org>,
Eric Dumazet <edumazet@google.com>,
Eric Dumazet <eric.dumazet@gmail.com>
Subject: [PATCH net-next 01/17] net: add networking namespace refcount tracker
Date: Mon, 6 Dec 2021 16:51:26 -0800 [thread overview]
Message-ID: <20211207005142.1688204-2-eric.dumazet@gmail.com> (raw)
In-Reply-To: <20211207005142.1688204-1-eric.dumazet@gmail.com>
From: Eric Dumazet <edumazet@google.com>
We have 100+ syzbot reports about netns being dismantled too soon,
still unresolved as of today.
We think a missing get_net() or an extra put_net() is the root cause.
In order to find the bug(s), and be able to spot future ones,
this patch adds CONFIG_NET_NS_REFCNT_TRACKER and new helpers
to precisely pair all put_net() with corresponding get_net().
To use these helpers, each data structure owning a refcount
should also use a "netns_tracker" to pair the get and put.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/linux/netdevice.h | 9 +--------
include/net/net_namespace.h | 34 ++++++++++++++++++++++++++++++++++
include/net/net_trackers.h | 18 ++++++++++++++++++
net/Kconfig.debug | 9 +++++++++
net/core/net_namespace.c | 3 +++
5 files changed, 65 insertions(+), 8 deletions(-)
create mode 100644 include/net/net_trackers.h
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 69dca1edd5a60f4b9df79fbf8dcbc878440ab4b8..201d8c5be80685f89d7fdba4b61f83194beb9b13 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -48,7 +48,7 @@
#include <uapi/linux/pkt_cls.h>
#include <linux/hashtable.h>
#include <linux/rbtree.h>
-#include <linux/ref_tracker.h>
+#include <net/net_trackers.h>
struct netpoll_info;
struct device;
@@ -300,13 +300,6 @@ enum netdev_state_t {
__LINK_STATE_TESTING,
};
-
-#ifdef CONFIG_NET_DEV_REFCNT_TRACKER
-typedef struct ref_tracker *netdevice_tracker;
-#else
-typedef struct {} netdevice_tracker;
-#endif
-
struct gro_list {
struct list_head list;
int count;
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index bb5fa59140321ba7c1826f5f4492e5cb607fd99f..5b61c462e534be468c81d2b0f4ef586b209dd4b8 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -34,6 +34,7 @@
#include <net/netns/smc.h>
#include <net/netns/bpf.h>
#include <net/netns/mctp.h>
+#include <net/net_trackers.h>
#include <linux/ns_common.h>
#include <linux/idr.h>
#include <linux/skbuff.h>
@@ -87,6 +88,7 @@ struct net {
struct idr netns_ids;
struct ns_common ns;
+ struct ref_tracker_dir refcnt_tracker;
struct list_head dev_base_head;
struct proc_dir_entry *proc_net;
@@ -240,6 +242,7 @@ void ipx_unregister_sysctl(void);
#ifdef CONFIG_NET_NS
void __put_net(struct net *net);
+/* Try using get_net_track() instead */
static inline struct net *get_net(struct net *net)
{
refcount_inc(&net->ns.count);
@@ -258,6 +261,7 @@ static inline struct net *maybe_get_net(struct net *net)
return net;
}
+/* Try using put_net_track() instead */
static inline void put_net(struct net *net)
{
if (refcount_dec_and_test(&net->ns.count))
@@ -308,6 +312,36 @@ static inline int check_net(const struct net *net)
#endif
+static inline void netns_tracker_alloc(struct net *net,
+ netns_tracker *tracker, gfp_t gfp)
+{
+#ifdef CONFIG_NET_NS_REFCNT_TRACKER
+ ref_tracker_alloc(&net->refcnt_tracker, tracker, gfp);
+#endif
+}
+
+static inline void netns_tracker_free(struct net *net,
+ netns_tracker *tracker)
+{
+#ifdef CONFIG_NET_NS_REFCNT_TRACKER
+ ref_tracker_free(&net->refcnt_tracker, tracker);
+#endif
+}
+
+static inline struct net *get_net_track(struct net *net,
+ netns_tracker *tracker, gfp_t gfp)
+{
+ get_net(net);
+ netns_tracker_alloc(net, tracker, gfp);
+ return net;
+}
+
+static inline void put_net_track(struct net *net, netns_tracker *tracker)
+{
+ netns_tracker_free(net, tracker);
+ put_net(net);
+}
+
typedef struct {
#ifdef CONFIG_NET_NS
struct net *net;
diff --git a/include/net/net_trackers.h b/include/net/net_trackers.h
new file mode 100644
index 0000000000000000000000000000000000000000..d94c76cf15a9df918441b8ab4ed20422059f7ed9
--- /dev/null
+++ b/include/net/net_trackers.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NET_NET_TRACKERS_H
+#define __NET_NET_TRACKERS_H
+#include <linux/ref_tracker.h>
+
+#ifdef CONFIG_NET_DEV_REFCNT_TRACKER
+typedef struct ref_tracker *netdevice_tracker;
+#else
+typedef struct {} netdevice_tracker;
+#endif
+
+#ifdef CONFIG_NET_NS_REFCNT_TRACKER
+typedef struct ref_tracker *netns_tracker;
+#else
+typedef struct {} netns_tracker;
+#endif
+
+#endif /* __NET_NET_TRACKERS_H */
diff --git a/net/Kconfig.debug b/net/Kconfig.debug
index fb5c70e01cb3b6f86afce9a9f0aa8f8d7468e1fe..2f50611df858911cf5190a361e4e9316e543ed3a 100644
--- a/net/Kconfig.debug
+++ b/net/Kconfig.debug
@@ -8,3 +8,12 @@ config NET_DEV_REFCNT_TRACKER
help
Enable debugging feature to track device references.
This adds memory and cpu costs.
+
+config NET_NS_REFCNT_TRACKER
+ bool "Enable networking namespace refcount tracking"
+ depends on DEBUG_KERNEL && STACKTRACE_SUPPORT
+ select REF_TRACKER
+ default n
+ help
+ Enable debugging feature to track netns references.
+ This adds memory and cpu costs.
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 202fa5eacd0f9bc74fc3246e9cebcd3419759ad5..9b7171c40434985b869c1477975fc75447d78c3b 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -311,6 +311,8 @@ static __net_init int setup_net(struct net *net, struct user_namespace *user_ns)
LIST_HEAD(net_exit_list);
refcount_set(&net->ns.count, 1);
+ ref_tracker_dir_init(&net->refcnt_tracker, 128);
+
refcount_set(&net->passive, 1);
get_random_bytes(&net->hash_mix, sizeof(u32));
preempt_disable();
@@ -635,6 +637,7 @@ static DECLARE_WORK(net_cleanup_work, cleanup_net);
void __put_net(struct net *net)
{
+ ref_tracker_dir_exit(&net->refcnt_tracker);
/* Cleanup the network namespace in process context */
if (llist_add(&net->cleanup_list, &cleanup_list))
queue_work(netns_wq, &net_cleanup_work);
--
2.34.1.400.ga245620fadb-goog
next prev parent reply other threads:[~2021-12-07 0:51 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
2021-12-07 0:51 ` Eric Dumazet [this message]
2021-12-07 0:51 ` [PATCH net-next 02/17] net: add netns refcount tracker to struct sock Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 03/17] net: add netns refcount tracker to struct seq_net_private Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 04/17] net: sched: add netns refcount tracker to struct tcf_exts Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 05/17] netfilter: nfnetlink: add netns refcount tracker to struct nfulnl_instance Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 06/17] l2tp: add netns refcount tracker to l2tp_dfs_seq_data Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 07/17] ppp: add netns refcount tracker Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 08/17] netfilter: nf_nat_masquerade: add netns refcount tracker to masq_dev_work Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 09/17] SUNRPC: add netns refcount tracker to struct svc_xprt Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 10/17] SUNRPC: add netns refcount tracker to struct gss_auth Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 11/17] SUNRPC: add netns refcount tracker to struct rpc_xprt Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 12/17] net: initialize init_net earlier Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 13/17] net: add netns refcount tracker to struct nsproxy Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 14/17] vfs: add netns refcount tracker to struct fs_context Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 15/17] audit: add netns refcount tracker to struct audit_net Eric Dumazet
2021-12-07 14:40 ` Jakub Kicinski
2021-12-07 0:51 ` [PATCH net-next 16/17] audit: add netns refcount tracker to struct audit_reply Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 17/17] audit: add netns refcount tracker to struct audit_netlink_list Eric Dumazet
2021-12-09 20:03 ` [PATCH net-next 00/17] net: netns refcount tracking series Jakub Kicinski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211207005142.1688204-2-eric.dumazet@gmail.com \
--to=eric.dumazet@gmail.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).