* [PATCH net-next 01/17] net: add networking namespace refcount tracker
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
@ 2021-12-07 0:51 ` Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 02/17] net: add netns refcount tracker to struct sock Eric Dumazet
` (16 subsequent siblings)
17 siblings, 0 replies; 20+ messages in thread
From: Eric Dumazet @ 2021-12-07 0:51 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
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
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH net-next 02/17] net: add netns refcount tracker to struct sock
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 01/17] net: add networking namespace refcount tracker Eric Dumazet
@ 2021-12-07 0:51 ` Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 03/17] net: add netns refcount tracker to struct seq_net_private Eric Dumazet
` (15 subsequent siblings)
17 siblings, 0 replies; 20+ messages in thread
From: Eric Dumazet @ 2021-12-07 0:51 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
From: Eric Dumazet <edumazet@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/net/sock.h | 2 ++
net/core/sock.c | 6 +++---
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/include/net/sock.h b/include/net/sock.h
index ae61cd0b650de76d731c8f9b7f9050d9beb3d87e..5d8532f26208fbd05f5b1185afa87207c1c476c9 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -350,6 +350,7 @@ struct bpf_local_storage;
* @sk_txtime_deadline_mode: set deadline mode for SO_TXTIME
* @sk_txtime_report_errors: set report errors mode for SO_TXTIME
* @sk_txtime_unused: unused txtime flags
+ * @ns_tracker: tracker for netns reference
*/
struct sock {
/*
@@ -538,6 +539,7 @@ struct sock {
struct bpf_local_storage __rcu *sk_bpf_storage;
#endif
struct rcu_head sk_rcu;
+ netns_tracker ns_tracker;
};
enum sk_pacing {
diff --git a/net/core/sock.c b/net/core/sock.c
index 4a499d255f401e61fff2fbab3b0fd9337da77f7e..1a6a925397906508a33e1443b1ec27ac19d036e1 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1983,7 +1983,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
sock_lock_init(sk);
sk->sk_net_refcnt = kern ? 0 : 1;
if (likely(sk->sk_net_refcnt)) {
- get_net(net);
+ get_net_track(net, &sk->ns_tracker, priority);
sock_inuse_add(net, 1);
}
@@ -2039,7 +2039,7 @@ static void __sk_destruct(struct rcu_head *head)
put_pid(sk->sk_peer_pid);
if (likely(sk->sk_net_refcnt))
- put_net(sock_net(sk));
+ put_net_track(sock_net(sk), &sk->ns_tracker);
sk_prot_free(sk->sk_prot_creator, sk);
}
@@ -2126,7 +2126,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
/* SANITY */
if (likely(newsk->sk_net_refcnt)) {
- get_net(sock_net(newsk));
+ get_net_track(sock_net(newsk), &newsk->ns_tracker, priority);
sock_inuse_add(sock_net(newsk), 1);
}
sk_node_init(&newsk->sk_node);
--
2.34.1.400.ga245620fadb-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH net-next 03/17] net: add netns refcount tracker to struct seq_net_private
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 01/17] net: add networking namespace refcount tracker Eric Dumazet
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 ` Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 04/17] net: sched: add netns refcount tracker to struct tcf_exts Eric Dumazet
` (14 subsequent siblings)
17 siblings, 0 replies; 20+ messages in thread
From: Eric Dumazet @ 2021-12-07 0:51 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
From: Eric Dumazet <edumazet@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
fs/proc/proc_net.c | 19 ++++++++++++++++---
include/linux/seq_file_net.h | 3 ++-
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index 15c2e55d2ed2c4b8b00209ecf9b18caa1a47f1b7..39b823ab2564edf62fd08983ec44560b1120ee24 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -61,15 +61,27 @@ static int seq_open_net(struct inode *inode, struct file *file)
}
#ifdef CONFIG_NET_NS
p->net = net;
+ netns_tracker_alloc(net, &p->ns_tracker, GFP_KERNEL);
#endif
return 0;
}
+static void seq_file_net_put_net(struct seq_file *seq)
+{
+#ifdef CONFIG_NET_NS
+ struct seq_net_private *priv = seq->private;
+
+ put_net_track(priv->net, &priv->ns_tracker);
+#else
+ put_net(&init_net);
+#endif
+}
+
static int seq_release_net(struct inode *ino, struct file *f)
{
struct seq_file *seq = f->private_data;
- put_net(seq_file_net(seq));
+ seq_file_net_put_net(seq);
seq_release_private(ino, f);
return 0;
}
@@ -87,7 +99,8 @@ int bpf_iter_init_seq_net(void *priv_data, struct bpf_iter_aux_info *aux)
#ifdef CONFIG_NET_NS
struct seq_net_private *p = priv_data;
- p->net = get_net(current->nsproxy->net_ns);
+ p->net = get_net_track(current->nsproxy->net_ns, &p->ns_tracker,
+ GFP_KERNEL);
#endif
return 0;
}
@@ -97,7 +110,7 @@ void bpf_iter_fini_seq_net(void *priv_data)
#ifdef CONFIG_NET_NS
struct seq_net_private *p = priv_data;
- put_net(p->net);
+ put_net_track(p->net, &p->ns_tracker);
#endif
}
diff --git a/include/linux/seq_file_net.h b/include/linux/seq_file_net.h
index 0fdbe1ddd8d1bd53269c4ca49297544860f3d3e5..b97912fdbae78304be7c3c45c862dce880e08dd4 100644
--- a/include/linux/seq_file_net.h
+++ b/include/linux/seq_file_net.h
@@ -9,7 +9,8 @@ extern struct net init_net;
struct seq_net_private {
#ifdef CONFIG_NET_NS
- struct net *net;
+ struct net *net;
+ netns_tracker ns_tracker;
#endif
};
--
2.34.1.400.ga245620fadb-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH net-next 04/17] net: sched: add netns refcount tracker to struct tcf_exts
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
` (2 preceding siblings ...)
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 ` Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 05/17] netfilter: nfnetlink: add netns refcount tracker to struct nfulnl_instance Eric Dumazet
` (13 subsequent siblings)
17 siblings, 0 replies; 20+ messages in thread
From: Eric Dumazet @ 2021-12-07 0:51 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
From: Eric Dumazet <edumazet@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/net/pkt_cls.h | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 193f88ebf629bd5a66c2d155346b40695e259a13..cebc1bd713b68e9c9c7b7656f569e749c0dc9297 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -202,7 +202,8 @@ struct tcf_exts {
__u32 type; /* for backward compat(TCA_OLD_COMPAT) */
int nr_actions;
struct tc_action **actions;
- struct net *net;
+ struct net *net;
+ netns_tracker ns_tracker;
#endif
/* Map to export classifier specific extension TLV types to the
* generic extensions API. Unsupported extensions must be set to 0.
@@ -218,6 +219,7 @@ static inline int tcf_exts_init(struct tcf_exts *exts, struct net *net,
exts->type = 0;
exts->nr_actions = 0;
exts->net = net;
+ netns_tracker_alloc(net, &exts->ns_tracker, GFP_KERNEL);
exts->actions = kcalloc(TCA_ACT_MAX_PRIO, sizeof(struct tc_action *),
GFP_KERNEL);
if (!exts->actions)
@@ -236,6 +238,8 @@ static inline bool tcf_exts_get_net(struct tcf_exts *exts)
{
#ifdef CONFIG_NET_CLS_ACT
exts->net = maybe_get_net(exts->net);
+ if (exts->net)
+ netns_tracker_alloc(exts->net, &exts->ns_tracker, GFP_KERNEL);
return exts->net != NULL;
#else
return true;
@@ -246,7 +250,7 @@ static inline void tcf_exts_put_net(struct tcf_exts *exts)
{
#ifdef CONFIG_NET_CLS_ACT
if (exts->net)
- put_net(exts->net);
+ put_net_track(exts->net, &exts->ns_tracker);
#endif
}
--
2.34.1.400.ga245620fadb-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH net-next 05/17] netfilter: nfnetlink: add netns refcount tracker to struct nfulnl_instance
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
` (3 preceding siblings ...)
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 ` Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 06/17] l2tp: add netns refcount tracker to l2tp_dfs_seq_data Eric Dumazet
` (12 subsequent siblings)
17 siblings, 0 replies; 20+ messages in thread
From: Eric Dumazet @ 2021-12-07 0:51 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
From: Eric Dumazet <edumazet@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
net/netfilter/nfnetlink_log.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 691ef4cffdd907cf09d3a7e680ebe83ea5562ee0..7a3a91fc7ffaaf7c632692949a990f5867173e5c 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -66,6 +66,7 @@ struct nfulnl_instance {
struct sk_buff *skb; /* pre-allocatd skb */
struct timer_list timer;
struct net *net;
+ netns_tracker ns_tracker;
struct user_namespace *peer_user_ns; /* User namespace of the peer process */
u32 peer_portid; /* PORTID of the peer process */
@@ -140,7 +141,7 @@ static void nfulnl_instance_free_rcu(struct rcu_head *head)
struct nfulnl_instance *inst =
container_of(head, struct nfulnl_instance, rcu);
- put_net(inst->net);
+ put_net_track(inst->net, &inst->ns_tracker);
kfree(inst);
module_put(THIS_MODULE);
}
@@ -187,7 +188,7 @@ instance_create(struct net *net, u_int16_t group_num,
timer_setup(&inst->timer, nfulnl_timer, 0);
- inst->net = get_net(net);
+ inst->net = get_net_track(net, &inst->ns_tracker, GFP_ATOMIC);
inst->peer_user_ns = user_ns;
inst->peer_portid = portid;
inst->group_num = group_num;
--
2.34.1.400.ga245620fadb-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH net-next 06/17] l2tp: add netns refcount tracker to l2tp_dfs_seq_data
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
` (4 preceding siblings ...)
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 ` Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 07/17] ppp: add netns refcount tracker Eric Dumazet
` (11 subsequent siblings)
17 siblings, 0 replies; 20+ messages in thread
From: Eric Dumazet @ 2021-12-07 0:51 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
From: Eric Dumazet <edumazet@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
net/l2tp/l2tp_debugfs.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/net/l2tp/l2tp_debugfs.c b/net/l2tp/l2tp_debugfs.c
index acf6e1343b88e070004f422e00d8fc697b4e4130..9d1aafe75f92dd7643c6908b83f4eb60ea79b025 100644
--- a/net/l2tp/l2tp_debugfs.c
+++ b/net/l2tp/l2tp_debugfs.c
@@ -32,7 +32,8 @@
static struct dentry *rootdir;
struct l2tp_dfs_seq_data {
- struct net *net;
+ struct net *net;
+ netns_tracker ns_tracker;
int tunnel_idx; /* current tunnel */
int session_idx; /* index of session within current tunnel */
struct l2tp_tunnel *tunnel;
@@ -281,7 +282,7 @@ static int l2tp_dfs_seq_open(struct inode *inode, struct file *file)
rc = PTR_ERR(pd->net);
goto err_free_pd;
}
-
+ netns_tracker_alloc(pd->net, &pd->ns_tracker, GFP_KERNEL);
rc = seq_open(file, &l2tp_dfs_seq_ops);
if (rc)
goto err_free_net;
@@ -293,7 +294,7 @@ static int l2tp_dfs_seq_open(struct inode *inode, struct file *file)
return rc;
err_free_net:
- put_net(pd->net);
+ put_net_track(pd->net, &pd->ns_tracker);
err_free_pd:
kfree(pd);
goto out;
@@ -307,7 +308,7 @@ static int l2tp_dfs_seq_release(struct inode *inode, struct file *file)
seq = file->private_data;
pd = seq->private;
if (pd->net)
- put_net(pd->net);
+ put_net_track(pd->net, &pd->ns_tracker);
kfree(pd);
seq_release(inode, file);
--
2.34.1.400.ga245620fadb-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH net-next 07/17] ppp: add netns refcount tracker
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
` (5 preceding siblings ...)
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 ` 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
` (10 subsequent siblings)
17 siblings, 0 replies; 20+ messages in thread
From: Eric Dumazet @ 2021-12-07 0:51 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
From: Eric Dumazet <edumazet@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
drivers/net/ppp/ppp_generic.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 1180a0e2445fbfb3204fea785f1c1cf48bc77141..9e52c5d2d77fce39b230605ec96fed9798858a13 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -173,6 +173,7 @@ struct channel {
spinlock_t downl; /* protects `chan', file.xq dequeue */
struct ppp *ppp; /* ppp unit we're connected to */
struct net *chan_net; /* the net channel belongs to */
+ netns_tracker ns_tracker;
struct list_head clist; /* link in list of channels per unit */
rwlock_t upl; /* protects `ppp' and 'bridge' */
struct channel __rcu *bridge; /* "bridged" ppp channel */
@@ -2879,7 +2880,7 @@ int ppp_register_net_channel(struct net *net, struct ppp_channel *chan)
pch->ppp = NULL;
pch->chan = chan;
- pch->chan_net = get_net(net);
+ pch->chan_net = get_net_track(net, &pch->ns_tracker, GFP_KERNEL);
chan->ppp = pch;
init_ppp_file(&pch->file, CHANNEL);
pch->file.hdrlen = chan->hdrlen;
@@ -3519,7 +3520,7 @@ ppp_disconnect_channel(struct channel *pch)
*/
static void ppp_destroy_channel(struct channel *pch)
{
- put_net(pch->chan_net);
+ put_net_track(pch->chan_net, &pch->ns_tracker);
pch->chan_net = NULL;
atomic_dec(&channel_count);
--
2.34.1.400.ga245620fadb-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH net-next 08/17] netfilter: nf_nat_masquerade: add netns refcount tracker to masq_dev_work
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
` (6 preceding siblings ...)
2021-12-07 0:51 ` [PATCH net-next 07/17] ppp: add netns refcount tracker Eric Dumazet
@ 2021-12-07 0:51 ` Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 09/17] SUNRPC: add netns refcount tracker to struct svc_xprt Eric Dumazet
` (9 subsequent siblings)
17 siblings, 0 replies; 20+ messages in thread
From: Eric Dumazet @ 2021-12-07 0:51 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
From: Eric Dumazet <edumazet@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
net/netfilter/nf_nat_masquerade.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/netfilter/nf_nat_masquerade.c b/net/netfilter/nf_nat_masquerade.c
index acd73f717a0883d791fc351851a98bac4144705f..e32fac374608576d6237f80b1bff558e9453585a 100644
--- a/net/netfilter/nf_nat_masquerade.c
+++ b/net/netfilter/nf_nat_masquerade.c
@@ -12,6 +12,7 @@
struct masq_dev_work {
struct work_struct work;
struct net *net;
+ netns_tracker ns_tracker;
union nf_inet_addr addr;
int ifindex;
int (*iter)(struct nf_conn *i, void *data);
@@ -82,7 +83,7 @@ static void iterate_cleanup_work(struct work_struct *work)
nf_ct_iterate_cleanup_net(w->net, w->iter, (void *)w, 0, 0);
- put_net(w->net);
+ put_net_track(w->net, &w->ns_tracker);
kfree(w);
atomic_dec(&masq_worker_count);
module_put(THIS_MODULE);
@@ -119,6 +120,7 @@ static void nf_nat_masq_schedule(struct net *net, union nf_inet_addr *addr,
INIT_WORK(&w->work, iterate_cleanup_work);
w->ifindex = ifindex;
w->net = net;
+ netns_tracker_alloc(net, &w->ns_tracker, gfp_flags);
w->iter = iter;
if (addr)
w->addr = *addr;
--
2.34.1.400.ga245620fadb-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH net-next 09/17] SUNRPC: add netns refcount tracker to struct svc_xprt
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
` (7 preceding siblings ...)
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 ` Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 10/17] SUNRPC: add netns refcount tracker to struct gss_auth Eric Dumazet
` (8 subsequent siblings)
17 siblings, 0 replies; 20+ messages in thread
From: Eric Dumazet @ 2021-12-07 0:51 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
From: Eric Dumazet <edumazet@google.com>
struct svc_xprt holds a long lived reference to a netns,
it is worth tracking it.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/linux/sunrpc/svc_xprt.h | 1 +
net/sunrpc/svc_xprt.c | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h
index 571f605bc91ef8fa190e7fd5504efb76ec3fa89e..382af90320acc3a7b3817bf66f65fbb15447ae7d 100644
--- a/include/linux/sunrpc/svc_xprt.h
+++ b/include/linux/sunrpc/svc_xprt.h
@@ -88,6 +88,7 @@ struct svc_xprt {
struct list_head xpt_users; /* callbacks on free */
struct net *xpt_net;
+ netns_tracker ns_tracker;
const struct cred *xpt_cred;
struct rpc_xprt *xpt_bc_xprt; /* NFSv4.1 backchannel */
struct rpc_xprt_switch *xpt_bc_xps; /* NFSv4.1 backchannel */
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index 1e99ba1b9d723d007ec3a00044b5ff922b7d8e56..16ae461fad1412dfc34192dcbdad494910a147f7 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -161,7 +161,7 @@ static void svc_xprt_free(struct kref *kref)
if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags))
svcauth_unix_info_release(xprt);
put_cred(xprt->xpt_cred);
- put_net(xprt->xpt_net);
+ put_net_track(xprt->xpt_net, &xprt->ns_tracker);
/* See comment on corresponding get in xs_setup_bc_tcp(): */
if (xprt->xpt_bc_xprt)
xprt_put(xprt->xpt_bc_xprt);
@@ -197,7 +197,7 @@ void svc_xprt_init(struct net *net, struct svc_xprt_class *xcl,
mutex_init(&xprt->xpt_mutex);
spin_lock_init(&xprt->xpt_lock);
set_bit(XPT_BUSY, &xprt->xpt_flags);
- xprt->xpt_net = get_net(net);
+ xprt->xpt_net = get_net_track(net, &xprt->ns_tracker, GFP_ATOMIC);
strcpy(xprt->xpt_remotebuf, "uninitialized");
}
EXPORT_SYMBOL_GPL(svc_xprt_init);
--
2.34.1.400.ga245620fadb-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH net-next 10/17] SUNRPC: add netns refcount tracker to struct gss_auth
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
` (8 preceding siblings ...)
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 ` Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 11/17] SUNRPC: add netns refcount tracker to struct rpc_xprt Eric Dumazet
` (7 subsequent siblings)
17 siblings, 0 replies; 20+ messages in thread
From: Eric Dumazet @ 2021-12-07 0:51 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
From: Eric Dumazet <edumazet@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
net/sunrpc/auth_gss/auth_gss.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 5f42aa5fc612850b526c160ab5e5c75416862676..8eb7e8544815a8bc20a79b21b01e3ba110fc6b47 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -72,7 +72,8 @@ struct gss_auth {
struct gss_api_mech *mech;
enum rpc_gss_svc service;
struct rpc_clnt *client;
- struct net *net;
+ struct net *net;
+ netns_tracker ns_tracker;
/*
* There are two upcall pipes; dentry[1], named "gssd", is used
* for the new text-based upcall; dentry[0] is named after the
@@ -1013,7 +1014,8 @@ gss_create_new(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
goto err_free;
}
gss_auth->client = clnt;
- gss_auth->net = get_net(rpc_net_ns(clnt));
+ gss_auth->net = get_net_track(rpc_net_ns(clnt), &gss_auth->ns_tracker,
+ GFP_KERNEL);
err = -EINVAL;
gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor);
if (!gss_auth->mech)
@@ -1068,7 +1070,7 @@ gss_create_new(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
err_put_mech:
gss_mech_put(gss_auth->mech);
err_put_net:
- put_net(gss_auth->net);
+ put_net_track(gss_auth->net, &gss_auth->ns_tracker);
err_free:
kfree(gss_auth->target_name);
kfree(gss_auth);
@@ -1084,7 +1086,7 @@ gss_free(struct gss_auth *gss_auth)
gss_pipe_free(gss_auth->gss_pipe[0]);
gss_pipe_free(gss_auth->gss_pipe[1]);
gss_mech_put(gss_auth->mech);
- put_net(gss_auth->net);
+ put_net_track(gss_auth->net, &gss_auth->ns_tracker);
kfree(gss_auth->target_name);
kfree(gss_auth);
--
2.34.1.400.ga245620fadb-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH net-next 11/17] SUNRPC: add netns refcount tracker to struct rpc_xprt
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
` (9 preceding siblings ...)
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 ` Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 12/17] net: initialize init_net earlier Eric Dumazet
` (6 subsequent siblings)
17 siblings, 0 replies; 20+ messages in thread
From: Eric Dumazet @ 2021-12-07 0:51 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
From: Eric Dumazet <edumazet@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/linux/sunrpc/xprt.h | 1 +
net/sunrpc/xprt.c | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 955ea4d7af0b2fea1300a46fad963df35f25810c..3cdc8d878d81122e3318447df4770100500403e4 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -284,6 +284,7 @@ struct rpc_xprt {
} stat;
struct net *xprt_net;
+ netns_tracker ns_tracker;
const char *servername;
const char *address_strings[RPC_DISPLAY_MAX];
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index a02de2bddb28b48bb6798327c0814e769314621b..5af484d6ba5e8bfb871768122009ee330c708c04 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1835,7 +1835,7 @@ EXPORT_SYMBOL_GPL(xprt_alloc);
void xprt_free(struct rpc_xprt *xprt)
{
- put_net(xprt->xprt_net);
+ put_net_track(xprt->xprt_net, &xprt->ns_tracker);
xprt_free_all_slots(xprt);
xprt_free_id(xprt);
rpc_sysfs_xprt_destroy(xprt);
@@ -2027,7 +2027,7 @@ static void xprt_init(struct rpc_xprt *xprt, struct net *net)
xprt_init_xid(xprt);
- xprt->xprt_net = get_net(net);
+ xprt->xprt_net = get_net_track(net, &xprt->ns_tracker, GFP_KERNEL);
}
/**
--
2.34.1.400.ga245620fadb-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH net-next 12/17] net: initialize init_net earlier
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
` (10 preceding siblings ...)
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 ` Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 13/17] net: add netns refcount tracker to struct nsproxy Eric Dumazet
` (5 subsequent siblings)
17 siblings, 0 replies; 20+ messages in thread
From: Eric Dumazet @ 2021-12-07 0:51 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
From: Eric Dumazet <edumazet@google.com>
While testing the following patch in the series
("net: add netns refcount tracker to struct nsproxy")
I found that devtmpfs_init() was called before init_net
was initialized.
This is a bug, because devtmpfs_setup() calls
ksys_unshare(CLONE_NEWNS);
This has the effect of increasing init_net refcount,
which will be later overwritten to 1, as part of setup_net(&init_net)
We had too many prior patches [1] trying to work around the root cause.
Really, make sure init_net is in BSS section, and that net_ns_init()
is called earlier at boot time.
Note that this following patchn in the series ("vfs: add netns refcount tracker
to struct fs_context") also will need net_ns_init() being called
before vfs_caches_init()
This saves around 4KB in .data section.
[1]
f8c46cb39079 ("netns: do not call pernet ops for not yet set up init_net namespace")
b5082df8019a ("net: Initialise init_net.count to 1")
734b65417b24 ("net: Statically initialize init_net.dev_base_head")
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/net/net_namespace.h | 6 ++++++
init/main.c | 2 ++
net/core/dev.c | 3 +--
net/core/net_namespace.c | 17 +++++------------
4 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 5b61c462e534be468c81d2b0f4ef586b209dd4b8..2ecbd7c11c88e016b1a6a450f07ee2cd94048f62 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -513,4 +513,10 @@ static inline void fnhe_genid_bump(struct net *net)
atomic_inc(&net->fnhe_genid);
}
+#ifdef CONFIG_NET
+void net_ns_init(void);
+#else
+static inline net_ns_init(void) {}
+#endif
+
#endif /* __NET_NET_NAMESPACE_H */
diff --git a/init/main.c b/init/main.c
index bb984ed79de0ea49b9a298c209c0c2f7e6f70941..cb68bc48a682c73340ceca28c2ba02fac1dda09d 100644
--- a/init/main.c
+++ b/init/main.c
@@ -99,6 +99,7 @@
#include <linux/kcsan.h>
#include <linux/init_syscalls.h>
#include <linux/stackdepot.h>
+#include <net/net_namespace.h>
#include <asm/io.h>
#include <asm/bugs.h>
@@ -1113,6 +1114,7 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
key_init();
security_init();
dbg_late_init();
+ net_ns_init();
vfs_caches_init();
pagecache_init();
signals_init();
diff --git a/net/core/dev.c b/net/core/dev.c
index 4420086f3aeb34614fc8222206dff2b2caa31d02..2ee7c87aa2ec8638131169d73a3ec699d5b292b3 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -10720,8 +10720,7 @@ static int __net_init netdev_init(struct net *net)
BUILD_BUG_ON(GRO_HASH_BUCKETS >
8 * sizeof_field(struct napi_struct, gro_bitmask));
- if (net != &init_net)
- INIT_LIST_HEAD(&net->dev_base_head);
+ INIT_LIST_HEAD(&net->dev_base_head);
net->dev_name_head = netdev_create_hash();
if (net->dev_name_head == NULL)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 9b7171c40434985b869c1477975fc75447d78c3b..3ea5321430ee21af687510917da9b9aea5154e12 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -44,13 +44,7 @@ EXPORT_SYMBOL_GPL(net_rwsem);
static struct key_tag init_net_key_domain = { .usage = REFCOUNT_INIT(1) };
#endif
-struct net init_net = {
- .ns.count = REFCOUNT_INIT(1),
- .dev_base_head = LIST_HEAD_INIT(init_net.dev_base_head),
-#ifdef CONFIG_KEYS
- .key_domain = &init_net_key_domain,
-#endif
-};
+struct net init_net;
EXPORT_SYMBOL(init_net);
static bool init_net_initialized;
@@ -1082,7 +1076,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id, u32 portid,
rtnl_set_sk_err(net, RTNLGRP_NSID, err);
}
-static int __init net_ns_init(void)
+void __init net_ns_init(void)
{
struct net_generic *ng;
@@ -1103,6 +1097,9 @@ static int __init net_ns_init(void)
rcu_assign_pointer(init_net.gen, ng);
+#ifdef CONFIG_KEYS
+ init_net.key_domain = &init_net_key_domain;
+#endif
down_write(&pernet_ops_rwsem);
if (setup_net(&init_net, &init_user_ns))
panic("Could not setup the initial network namespace");
@@ -1117,12 +1114,8 @@ static int __init net_ns_init(void)
RTNL_FLAG_DOIT_UNLOCKED);
rtnl_register(PF_UNSPEC, RTM_GETNSID, rtnl_net_getid, rtnl_net_dumpid,
RTNL_FLAG_DOIT_UNLOCKED);
-
- return 0;
}
-pure_initcall(net_ns_init);
-
static void free_exit_list(struct pernet_operations *ops, struct list_head *net_exit_list)
{
ops_pre_exit_list(ops, net_exit_list);
--
2.34.1.400.ga245620fadb-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH net-next 13/17] net: add netns refcount tracker to struct nsproxy
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
` (11 preceding siblings ...)
2021-12-07 0:51 ` [PATCH net-next 12/17] net: initialize init_net earlier Eric Dumazet
@ 2021-12-07 0:51 ` Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 14/17] vfs: add netns refcount tracker to struct fs_context Eric Dumazet
` (4 subsequent siblings)
17 siblings, 0 replies; 20+ messages in thread
From: Eric Dumazet @ 2021-12-07 0:51 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
From: Eric Dumazet <edumazet@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/linux/nsproxy.h | 2 ++
kernel/nsproxy.c | 5 +++--
net/core/net_namespace.c | 4 ++--
3 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index cdb171efc7cb052dd4844ae182206939627c68e8..eed7768daf428cfede70f438ecd366af23da85f2 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -4,6 +4,7 @@
#include <linux/spinlock.h>
#include <linux/sched.h>
+#include <net/net_trackers.h>
struct mnt_namespace;
struct uts_namespace;
@@ -35,6 +36,7 @@ struct nsproxy {
struct mnt_namespace *mnt_ns;
struct pid_namespace *pid_ns_for_children;
struct net *net_ns;
+ netns_tracker ns_tracker;
struct time_namespace *time_ns;
struct time_namespace *time_ns_for_children;
struct cgroup_namespace *cgroup_ns;
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index eec72ca962e249c94266192b77a3c1f92ec8e889..8b50e8153bc8957b47e2fce860aacce4e9f56616 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -112,6 +112,7 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
err = PTR_ERR(new_nsp->net_ns);
goto out_net;
}
+ netns_tracker_alloc(new_nsp->net_ns, &new_nsp->ns_tracker, GFP_KERNEL);
new_nsp->time_ns_for_children = copy_time_ns(flags, user_ns,
tsk->nsproxy->time_ns_for_children);
@@ -124,7 +125,7 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
return new_nsp;
out_time:
- put_net(new_nsp->net_ns);
+ put_net_track(new_nsp->net_ns, &new_nsp->ns_tracker);
out_net:
put_cgroup_ns(new_nsp->cgroup_ns);
out_cgroup:
@@ -200,7 +201,7 @@ void free_nsproxy(struct nsproxy *ns)
if (ns->time_ns_for_children)
put_time_ns(ns->time_ns_for_children);
put_cgroup_ns(ns->cgroup_ns);
- put_net(ns->net_ns);
+ put_net_track(ns->net_ns, &ns->ns_tracker);
kmem_cache_free(nsproxy_cachep, ns);
}
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 3ea5321430ee21af687510917da9b9aea5154e12..962062ad8cc4697ff6791aea7c48aea0b5db94a5 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -1355,8 +1355,8 @@ static int netns_install(struct nsset *nsset, struct ns_common *ns)
!ns_capable(nsset->cred->user_ns, CAP_SYS_ADMIN))
return -EPERM;
- put_net(nsproxy->net_ns);
- nsproxy->net_ns = get_net(net);
+ put_net_track(nsproxy->net_ns, &nsproxy->ns_tracker);
+ nsproxy->net_ns = get_net_track(net, &nsproxy->ns_tracker, GFP_KERNEL);
return 0;
}
--
2.34.1.400.ga245620fadb-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH net-next 14/17] vfs: add netns refcount tracker to struct fs_context
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
` (12 preceding siblings ...)
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 ` Eric Dumazet
2021-12-07 0:51 ` [PATCH net-next 15/17] audit: add netns refcount tracker to struct audit_net Eric Dumazet
` (3 subsequent siblings)
17 siblings, 0 replies; 20+ messages in thread
From: Eric Dumazet @ 2021-12-07 0:51 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
From: Eric Dumazet <edumazet@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
fs/afs/mntpt.c | 5 +++--
fs/fs_context.c | 7 ++++---
fs/nfs/fs_context.c | 5 +++--
fs/nfs/namespace.c | 5 +++--
include/linux/fs_context.h | 2 ++
5 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index bbb2c210d139d9033e83e39f0c4778de83afc694..c67474607604cc8096cfe343893994fe4153ffb4 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -78,8 +78,9 @@ static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt)
int ret;
if (fc->net_ns != src_as->net_ns) {
- put_net(fc->net_ns);
- fc->net_ns = get_net(src_as->net_ns);
+ put_net_track(fc->net_ns, &fc->ns_tracker);
+ fc->net_ns = get_net_track(src_as->net_ns, &fc->ns_tracker,
+ GFP_KERNEL);
}
if (src_as->volume && src_as->volume->type == AFSVL_RWVOL) {
diff --git a/fs/fs_context.c b/fs/fs_context.c
index b7e43a780a625bca1b0faeba53e2702463ad0496..06ece7c4b4c295cd1d918378597a23ac3a3cb13e 100644
--- a/fs/fs_context.c
+++ b/fs/fs_context.c
@@ -263,7 +263,8 @@ static struct fs_context *alloc_fs_context(struct file_system_type *fs_type,
fc->sb_flags_mask = sb_flags_mask;
fc->fs_type = get_filesystem(fs_type);
fc->cred = get_current_cred();
- fc->net_ns = get_net(current->nsproxy->net_ns);
+ fc->net_ns = get_net_track(current->nsproxy->net_ns,
+ &fc->ns_tracker, GFP_KERNEL);
fc->log.prefix = fs_type->name;
mutex_init(&fc->uapi_mutex);
@@ -355,7 +356,7 @@ struct fs_context *vfs_dup_fs_context(struct fs_context *src_fc)
fc->source = NULL;
fc->security = NULL;
get_filesystem(fc->fs_type);
- get_net(fc->net_ns);
+ get_net_track(fc->net_ns, &fc->ns_tracker, GFP_KERNEL);
get_user_ns(fc->user_ns);
get_cred(fc->cred);
if (fc->log.log)
@@ -469,7 +470,7 @@ void put_fs_context(struct fs_context *fc)
fc->ops->free(fc);
security_free_mnt_opts(&fc->security);
- put_net(fc->net_ns);
+ put_net_track(fc->net_ns, &fc->ns_tracker);
put_user_ns(fc->user_ns);
put_cred(fc->cred);
put_fc_log(fc);
diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c
index 0d444a90f513a9fa6d2cef1748a7218575a38d84..ea0bd82a29ecb498d995ef74b1a4c0fc1832116d 100644
--- a/fs/nfs/fs_context.c
+++ b/fs/nfs/fs_context.c
@@ -1531,8 +1531,9 @@ static int nfs_init_fs_context(struct fs_context *fc)
ctx->nfs_server.addrlen);
if (fc->net_ns != net) {
- put_net(fc->net_ns);
- fc->net_ns = get_net(net);
+ put_net_track(fc->net_ns, &fc->ns_tracker);
+ fc->net_ns = get_net_track(net, &fc->ns_tracker,
+ GFP_KERNEL);
}
ctx->nfs_mod = nfss->nfs_client->cl_nfs_mod;
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 3295af4110f1b1c5890f110c3d49424a3d19406f..8c630907d1eff2f7199d32d6becee4c10259473d 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -170,8 +170,9 @@ struct vfsmount *nfs_d_automount(struct path *path)
goto out_fc;
if (fc->net_ns != client->cl_net) {
- put_net(fc->net_ns);
- fc->net_ns = get_net(client->cl_net);
+ put_net_track(fc->net_ns, &fc->ns_tracker);
+ fc->net_ns = get_net_track(client->cl_net,
+ &fc->ns_tracker, GFP_KERNEL);
}
/* for submounts we want the same server; referrals will reassign */
diff --git a/include/linux/fs_context.h b/include/linux/fs_context.h
index 6b54982fc5f378ec704f56def2fdb299e7d8b42d..9099bf7769c6db04b649d319502aec1b17d3d236 100644
--- a/include/linux/fs_context.h
+++ b/include/linux/fs_context.h
@@ -13,6 +13,7 @@
#include <linux/errno.h>
#include <linux/security.h>
#include <linux/mutex.h>
+#include <net/net_trackers.h>
struct cred;
struct dentry;
@@ -96,6 +97,7 @@ struct fs_context {
struct dentry *root; /* The root and superblock */
struct user_namespace *user_ns; /* The user namespace for this mount */
struct net *net_ns; /* The network namespace for this mount */
+ netns_tracker ns_tracker; /* Tracker for @net_ns reference */
const struct cred *cred; /* The mounter's credentials */
struct p_log log; /* Logging buffer */
const char *source; /* The source name (eg. dev path) */
--
2.34.1.400.ga245620fadb-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH net-next 15/17] audit: add netns refcount tracker to struct audit_net
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
` (13 preceding siblings ...)
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 ` 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
` (2 subsequent siblings)
17 siblings, 1 reply; 20+ messages in thread
From: Eric Dumazet @ 2021-12-07 0:51 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
From: Eric Dumazet <edumazet@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
kernel/audit.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 121d37e700a62b53854c06199d9a89850ec39dd4..27013414847678af4283484feab2461e3d9c67ed 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -96,6 +96,7 @@ struct audit_net {
* @pid: auditd PID
* @portid: netlink portid
* @net: the associated network namespace
+ * ns_tracker: tracker for @net reference
* @rcu: RCU head
*
* Description:
@@ -106,6 +107,7 @@ struct auditd_connection {
struct pid *pid;
u32 portid;
struct net *net;
+ netns_tracker ns_tracker;
struct rcu_head rcu;
};
static struct auditd_connection __rcu *auditd_conn;
@@ -481,7 +483,7 @@ static void auditd_conn_free(struct rcu_head *rcu)
ac = container_of(rcu, struct auditd_connection, rcu);
put_pid(ac->pid);
- put_net(ac->net);
+ put_net_track(ac->net, &ac->ns_tracker);
kfree(ac);
}
@@ -508,7 +510,7 @@ static int auditd_set(struct pid *pid, u32 portid, struct net *net)
return -ENOMEM;
ac_new->pid = get_pid(pid);
ac_new->portid = portid;
- ac_new->net = get_net(net);
+ ac_new->net = get_net_track(net, &ac_new->ns_tracker, GFP_KERNEL);
spin_lock_irqsave(&auditd_conn_lock, flags);
ac_old = rcu_dereference_protected(auditd_conn,
--
2.34.1.400.ga245620fadb-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH net-next 15/17] audit: add netns refcount tracker to struct audit_net
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
0 siblings, 0 replies; 20+ messages in thread
From: Jakub Kicinski @ 2021-12-07 14:40 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David S . Miller, netdev, Eric Dumazet
On Mon, 6 Dec 2021 16:51:40 -0800 Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> ---
> kernel/audit.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/kernel/audit.c b/kernel/audit.c
> index 121d37e700a62b53854c06199d9a89850ec39dd4..27013414847678af4283484feab2461e3d9c67ed 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -96,6 +96,7 @@ struct audit_net {
> * @pid: auditd PID
> * @portid: netlink portid
> * @net: the associated network namespace
> + * ns_tracker: tracker for @net reference
You need the '@' sign. I'll add it when applying.
> * @rcu: RCU head
> *
> * Description:
> @@ -106,6 +107,7 @@ struct auditd_connection {
> struct pid *pid;
> u32 portid;
> struct net *net;
> + netns_tracker ns_tracker;
> struct rcu_head rcu;
> };
> static struct auditd_connection __rcu *auditd_conn;
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH net-next 16/17] audit: add netns refcount tracker to struct audit_reply
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
` (14 preceding siblings ...)
2021-12-07 0:51 ` [PATCH net-next 15/17] audit: add netns refcount tracker to struct audit_net Eric Dumazet
@ 2021-12-07 0:51 ` 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
17 siblings, 0 replies; 20+ messages in thread
From: Eric Dumazet @ 2021-12-07 0:51 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
From: Eric Dumazet <edumazet@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
kernel/audit.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 27013414847678af4283484feab2461e3d9c67ed..493365899d205c12338323b5a6ca6a30609a3d6a 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -207,6 +207,7 @@ struct audit_buffer {
struct audit_reply {
__u32 portid;
struct net *net;
+ netns_tracker ns_tracker;
struct sk_buff *skb;
};
@@ -938,7 +939,7 @@ static void audit_free_reply(struct audit_reply *reply)
kfree_skb(reply->skb);
if (reply->net)
- put_net(reply->net);
+ put_net_track(reply->net, &reply->ns_tracker);
kfree(reply);
}
@@ -982,7 +983,8 @@ static void audit_send_reply(struct sk_buff *request_skb, int seq, int type, int
reply->skb = audit_make_reply(seq, type, done, multi, payload, size);
if (!reply->skb)
goto err;
- reply->net = get_net(sock_net(NETLINK_CB(request_skb).sk));
+ reply->net = get_net_track(sock_net(NETLINK_CB(request_skb).sk),
+ &reply->ns_tracker, GFP_KERNEL);
reply->portid = NETLINK_CB(request_skb).portid;
tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply");
--
2.34.1.400.ga245620fadb-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH net-next 17/17] audit: add netns refcount tracker to struct audit_netlink_list
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
` (15 preceding siblings ...)
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 ` Eric Dumazet
2021-12-09 20:03 ` [PATCH net-next 00/17] net: netns refcount tracking series Jakub Kicinski
17 siblings, 0 replies; 20+ messages in thread
From: Eric Dumazet @ 2021-12-07 0:51 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
From: Eric Dumazet <edumazet@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
kernel/audit.c | 2 +-
kernel/audit.h | 2 ++
kernel/auditfilter.c | 3 ++-
3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 493365899d205c12338323b5a6ca6a30609a3d6a..a5b360ecb379426bbfc743f13beeb6cddc96f068 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -901,7 +901,7 @@ int audit_send_list_thread(void *_dest)
while ((skb = __skb_dequeue(&dest->q)) != NULL)
netlink_unicast(sk, skb, dest->portid, 0);
- put_net(dest->net);
+ put_net_track(dest->net, &dest->ns_tracker);
kfree(dest);
return 0;
diff --git a/kernel/audit.h b/kernel/audit.h
index c4498090a5bd66e5c620368381c89d4dda14d851..ffa8b18d84ad170f8c76a213dba610b0e4986319 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -15,6 +15,7 @@
#include <uapi/linux/mqueue.h>
#include <linux/tty.h>
#include <uapi/linux/openat2.h> // struct open_how
+#include <net/net_trackers.h>
/* AUDIT_NAMES is the number of slots we reserve in the audit_context
* for saving names from getname(). If we get more names we will allocate
@@ -236,6 +237,7 @@ extern void audit_panic(const char *message);
struct audit_netlink_list {
__u32 portid;
struct net *net;
+ netns_tracker ns_tracker;
struct sk_buff_head q;
};
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index d75acb014ccdcba2a0bed0646323f5427757e493..2ea0c2ea9b7272a8abcd4c36a4d35f17e75e92e3 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1182,7 +1182,8 @@ int audit_list_rules_send(struct sk_buff *request_skb, int seq)
dest = kmalloc(sizeof(*dest), GFP_KERNEL);
if (!dest)
return -ENOMEM;
- dest->net = get_net(sock_net(NETLINK_CB(request_skb).sk));
+ dest->net = get_net_track(sock_net(NETLINK_CB(request_skb).sk),
+ &dest->ns_tracker, GFP_KERNEL);
dest->portid = NETLINK_CB(request_skb).portid;
skb_queue_head_init(&dest->q);
--
2.34.1.400.ga245620fadb-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH net-next 00/17] net: netns refcount tracking series
2021-12-07 0:51 [PATCH net-next 00/17] net: netns refcount tracking series Eric Dumazet
` (16 preceding siblings ...)
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 ` Jakub Kicinski
17 siblings, 0 replies; 20+ messages in thread
From: Jakub Kicinski @ 2021-12-09 20:03 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David S . Miller, netdev, Eric Dumazet
On Mon, 6 Dec 2021 16:51:25 -0800 Eric Dumazet wrote:
> 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().
>
> Small sections of codes where the get()/put() are in sight
> do not need to have a tracker, because they are short lived,
> but in theory it is also possible to declare an on-stack tracker.
Ugh, I realized after a week of waiting that vfs / sunrpc / audit folks
are not even CCed here. I think we should give them the courtesy of
being able to ack the patches.. Can you split out 1-4,6,7 for immediate
merging and repost the rest with the right CCs?
^ permalink raw reply [flat|nested] 20+ messages in thread