[patch v2 01/11] netlink: add reference of module in netlink_dump_start

Subsystems: networking [general], the rest

STALE5065d

12 messages, 2 authors, 2012-09-26 · open the first message on its own page

[patch v2 01/11] netlink: add reference of module in netlink_dump_start

From: Gao feng <hidden>
Date: 2012-09-26 08:46:21

I get a panic when I use ss -a and rmmod inet_diag at the
same time.

it's because netlink_dump use inet_diag_dump witch function
belongs to module inet_diag.

I search the codes and find many modules have the same problem.
We need add reference of the module witch the cb->dump belongs
to.

Thanks for all help from Stephen,Jan,Eric and Steffen.

Signed-off-by: Gao feng <redacted>
---
 include/linux/netlink.h  |    6 +++++-
 net/netlink/af_netlink.c |   25 +++++++++++++++++++++----
 2 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index f74dd13..381f7d6 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -232,6 +232,8 @@ struct netlink_callback {
 					struct netlink_callback *cb);
 	int			(*done)(struct netlink_callback *cb);
 	void			*data;
+	/* the module that dump function belong to */
+	struct module		*module;
 	u16			family;
 	u16			min_dump_alloc;
 	unsigned int		prev_seq, seq;
@@ -249,11 +251,13 @@ __nlmsg_put(struct sk_buff *skb, u32 pid, u32 seq, int type, int len, int flags)
 
 struct netlink_dump_control {
 	int (*dump)(struct sk_buff *skb, struct netlink_callback *);
-	int (*done)(struct netlink_callback*);
+	int (*done)(struct netlink_callback *);
 	void *data;
+	struct module *module;
 	u16 min_dump_alloc;
 };
 
+extern int netlink_dump_done(struct netlink_callback *cb);
 extern int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
 			      const struct nlmsghdr *nlh,
 			      struct netlink_dump_control *control);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 5270238..3190dae 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1769,6 +1769,13 @@ errout_skb:
 	return err;
 }
 
+int netlink_dump_done(struct netlink_callback *cb)
+{
+	module_put(cb->module);
+	return 0;
+}
+EXPORT_SYMBOL(netlink_dump_done);
+
 int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
 		       const struct nlmsghdr *nlh,
 		       struct netlink_dump_control *control)
@@ -1786,6 +1793,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
 	cb->done = control->done;
 	cb->nlh = nlh;
 	cb->data = control->data;
+	cb->module = control->module;
 	cb->min_dump_alloc = control->min_dump_alloc;
 	atomic_inc(&skb->users);
 	cb->skb = skb;
@@ -1796,19 +1804,28 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
 		return -ECONNREFUSED;
 	}
 	nlk = nlk_sk(sk);
-	/* A dump is in progress... */
+
 	mutex_lock(nlk->cb_mutex);
+	/* A dump is in progress... */
 	if (nlk->cb) {
 		mutex_unlock(nlk->cb_mutex);
 		netlink_destroy_callback(cb);
-		sock_put(sk);
-		return -EBUSY;
+		ret = -EBUSY;
+		goto out;
+	}
+	/* add reference of module witch cb->dump belong to */
+	if (!try_module_get(cb->module)) {
+		mutex_unlock(nlk->cb_mutex);
+		netlink_destroy_callback(cb);
+		ret = -EPROTONOSUPPORT;
+		goto out;
 	}
+
 	nlk->cb = cb;
 	mutex_unlock(nlk->cb_mutex);
 
 	ret = netlink_dump(sk);
-
+out:
 	sock_put(sk);
 
 	if (ret)
-- 
1.7.7.6

[patch v2 02/11] inet_diag: pass inet_diag module to netlink_dump_start

From: Gao feng <hidden>
Date: 2012-09-26 08:41:19

set netlink_dump_control.done and .module to avoid panic.

Signed-off-by: Gao feng <redacted>
---
 net/ipv4/inet_diag.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 570e61f..36d4be5 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -972,6 +972,8 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)
 		{
 			struct netlink_dump_control c = {
 				.dump = inet_diag_dump_compat,
+				.done = netlink_dump_done,
+				.module = THIS_MODULE,
 			};
 			return netlink_dump_start(net->diag_nlsk, skb, nlh, &c);
 		}
@@ -1001,6 +1003,8 @@ static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
 		{
 			struct netlink_dump_control c = {
 				.dump = inet_diag_dump,
+				.done = netlink_dump_done,
+				.module = THIS_MODULE,
 			};
 			return netlink_dump_start(net->diag_nlsk, skb, h, &c);
 		}
-- 
1.7.7.6

[patch v2 04/11] nf_conntrack_netlink: pass nf_conntrack_netlink module to netlink_dump_start

From: Gao feng <hidden>
Date: 2012-09-26 08:41:21

use proper netlink_dump_control.done and .module to avoid panic.

Signed-off-by: Gao feng <redacted>
---
 net/netfilter/nf_conntrack_netlink.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 9807f32..509a257 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -706,6 +706,7 @@ static int ctnetlink_done(struct netlink_callback *cb)
 		nf_ct_put((struct nf_conn *)cb->args[1]);
 	if (cb->data)
 		kfree(cb->data);
+	netlink_dump_done(cb);
 	return 0;
 }
 
@@ -1022,6 +1023,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
 		struct netlink_dump_control c = {
 			.dump = ctnetlink_dump_table,
 			.done = ctnetlink_done,
+			.module = THIS_MODULE,
 		};
 #ifdef CONFIG_NF_CONNTRACK_MARK
 		if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) {
@@ -1706,6 +1708,8 @@ ctnetlink_stat_ct_cpu(struct sock *ctnl, struct sk_buff *skb,
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		struct netlink_dump_control c = {
 			.dump = ctnetlink_ct_stat_cpu_dump,
+			.done = netlink_dump_done,
+			.module = THIS_MODULE,
 		};
 		return netlink_dump_start(ctnl, skb, nlh, &c);
 	}
@@ -2141,6 +2145,7 @@ static int ctnetlink_exp_done(struct netlink_callback *cb)
 {
 	if (cb->args[1])
 		nf_ct_expect_put((struct nf_conntrack_expect *)cb->args[1]);
+	netlink_dump_done(cb);
 	return 0;
 }
 
@@ -2222,6 +2227,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
 		struct netlink_dump_control c = {
 			.dump = ctnetlink_exp_dump_table,
 			.done = ctnetlink_exp_done,
+			.module = THIS_MODULE,
 		};
 		return netlink_dump_start(ctnl, skb, nlh, &c);
 	}
@@ -2660,6 +2666,8 @@ ctnetlink_stat_exp_cpu(struct sock *ctnl, struct sk_buff *skb,
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		struct netlink_dump_control c = {
 			.dump = ctnetlink_exp_stat_cpu_dump,
+			.done = netlink_dump_done,
+			.module = THIS_MODULE,
 		};
 		return netlink_dump_start(ctnl, skb, nlh, &c);
 	}
-- 
1.7.7.6

[patch v2 09/11] xfrm: pass xfrm_user module to netlink_dump_start

From: Gao feng <hidden>
Date: 2012-09-26 08:41:26

use proper netlink_dump_control.done and .module to avoid panic.

Signed-off-by: Gao feng <redacted>
---
 net/xfrm/xfrm_user.c |   12 ++++++++----
 1 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 289f4bf..852339d 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -867,7 +867,7 @@ static int xfrm_dump_sa_done(struct netlink_callback *cb)
 {
 	struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1];
 	xfrm_state_walk_done(walk);
-	return 0;
+	return netlink_dump_done(cb);
 }
 
 static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
@@ -1538,7 +1538,7 @@ static int xfrm_dump_policy_done(struct netlink_callback *cb)
 	struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];
 
 	xfrm_policy_walk_done(walk);
-	return 0;
+	return netlink_dump_done(cb);
 }
 
 static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb)
@@ -2308,17 +2308,20 @@ static struct xfrm_link {
 	int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
 	int (*dump)(struct sk_buff *, struct netlink_callback *);
 	int (*done)(struct netlink_callback *);
+	struct module *module;
 } xfrm_dispatch[XFRM_NR_MSGTYPES] = {
 	[XFRM_MSG_NEWSA       - XFRM_MSG_BASE] = { .doit = xfrm_add_sa        },
 	[XFRM_MSG_DELSA       - XFRM_MSG_BASE] = { .doit = xfrm_del_sa        },
 	[XFRM_MSG_GETSA       - XFRM_MSG_BASE] = { .doit = xfrm_get_sa,
 						   .dump = xfrm_dump_sa,
-						   .done = xfrm_dump_sa_done  },
+						   .done = xfrm_dump_sa_done,
+						   .module = THIS_MODULE      },
 	[XFRM_MSG_NEWPOLICY   - XFRM_MSG_BASE] = { .doit = xfrm_add_policy    },
 	[XFRM_MSG_DELPOLICY   - XFRM_MSG_BASE] = { .doit = xfrm_get_policy    },
 	[XFRM_MSG_GETPOLICY   - XFRM_MSG_BASE] = { .doit = xfrm_get_policy,
 						   .dump = xfrm_dump_policy,
-						   .done = xfrm_dump_policy_done },
+						   .done = xfrm_dump_policy_done,
+						   .module = THIS_MODULE      },
 	[XFRM_MSG_ALLOCSPI    - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi },
 	[XFRM_MSG_ACQUIRE     - XFRM_MSG_BASE] = { .doit = xfrm_add_acquire   },
 	[XFRM_MSG_EXPIRE      - XFRM_MSG_BASE] = { .doit = xfrm_add_sa_expire },
@@ -2362,6 +2365,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 			struct netlink_dump_control c = {
 				.dump = link->dump,
 				.done = link->done,
+				.module = link->module,
 			};
 			return netlink_dump_start(net->xfrm.nlsk, skb, nlh, &c);
 		}
-- 
1.7.7.6

[patch v2 05/11] nfnetlink_acct: pass nfnetlink_acct module to netlink_dump_start

From: Gao feng <hidden>
Date: 2012-09-26 08:46:17

use proper netlink_dump_control.done and .module to avoid panic.

Signed-off-by: Gao feng <redacted>
---
 net/netfilter/nfnetlink_acct.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c
index b2e7310..1e9cb0f 100644
--- a/net/netfilter/nfnetlink_acct.c
+++ b/net/netfilter/nfnetlink_acct.c
@@ -175,6 +175,8 @@ nfnl_acct_get(struct sock *nfnl, struct sk_buff *skb,
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		struct netlink_dump_control c = {
 			.dump = nfnl_acct_dump,
+			.done = netlink_dump_done,
+			.module = THIS_MODULE,
 		};
 		return netlink_dump_start(nfnl, skb, nlh, &c);
 	}
-- 
1.7.7.6

[patch v2 03/11] unix_diag: pass unix_diag module to netlink_dump_start

From: Gao feng <hidden>
Date: 2012-09-26 08:46:17

set netlink_dump_control.done and .module to avoid panic.

Signed-off-by: Gao feng <redacted>
---
 net/unix/diag.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/net/unix/diag.c b/net/unix/diag.c
index 750b134..5e09553 100644
--- a/net/unix/diag.c
+++ b/net/unix/diag.c
@@ -299,6 +299,8 @@ static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
 	if (h->nlmsg_flags & NLM_F_DUMP) {
 		struct netlink_dump_control c = {
 			.dump = unix_diag_dump,
+			.done = netlink_dump_done,
+			.module = THIS_MODULE,
 		};
 		return netlink_dump_start(net->diag_nlsk, skb, h, &c);
 	} else
-- 
1.7.7.6

[patch v2 08/11] crypto: pass crypto_user module to netlink_dump_start

From: Gao feng <hidden>
Date: 2012-09-26 08:46:23

use proper netlink_dump_control.done and .module to avoid panic.

Signed-off-by: Gao feng <redacted>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
---
 crypto/crypto_user.c |    7 +++++--
 1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index ba2c611..a9ca2b9 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -249,7 +249,7 @@ out_err:
 
 static int crypto_dump_report_done(struct netlink_callback *cb)
 {
-	return 0;
+	return netlink_dump_done(cb);
 }
 
 static int crypto_update_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -430,13 +430,15 @@ static struct crypto_link {
 	int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
 	int (*dump)(struct sk_buff *, struct netlink_callback *);
 	int (*done)(struct netlink_callback *);
+	struct module *module;
 } crypto_dispatch[CRYPTO_NR_MSGTYPES] = {
 	[CRYPTO_MSG_NEWALG	- CRYPTO_MSG_BASE] = { .doit = crypto_add_alg},
 	[CRYPTO_MSG_DELALG	- CRYPTO_MSG_BASE] = { .doit = crypto_del_alg},
 	[CRYPTO_MSG_UPDATEALG	- CRYPTO_MSG_BASE] = { .doit = crypto_update_alg},
 	[CRYPTO_MSG_GETALG	- CRYPTO_MSG_BASE] = { .doit = crypto_report,
 						       .dump = crypto_dump_report,
-						       .done = crypto_dump_report_done},
+						       .done = crypto_dump_report_done,
+						       .module = THIS_MODULE},
 };
 
 static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
@@ -470,6 +472,7 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 			struct netlink_dump_control c = {
 				.dump = link->dump,
 				.done = link->done,
+				.module = link->module,
 				.min_dump_alloc = dump_alloc,
 			};
 			return netlink_dump_start(crypto_nlsk, skb, nlh, &c);
-- 
1.7.7.6

Re: [patch v2 04/11] nf_conntrack_netlink: pass nf_conntrack_netlink module to netlink_dump_start

From: Gao feng <hidden>
Date: 2012-09-26 09:25:28

于 2012年09月26日 16:41, Gao feng 写道:
quoted hunk
use proper netlink_dump_control.done and .module to avoid panic.

Signed-off-by: Gao feng <redacted>
---
 net/netfilter/nf_conntrack_netlink.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 9807f32..509a257 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -706,6 +706,7 @@ static int ctnetlink_done(struct netlink_callback *cb)
 		nf_ct_put((struct nf_conn *)cb->args[1]);
 	if (cb->data)
 		kfree(cb->data);
+	netlink_dump_done(cb);
 	return 0;
 }
 
@@ -1022,6 +1023,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
 		struct netlink_dump_control c = {
 			.dump = ctnetlink_dump_table,
 			.done = ctnetlink_done,
+			.module = THIS_MODULE,
 		};
 #ifdef CONFIG_NF_CONNTRACK_MARK
 		if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) {
@@ -1706,6 +1708,8 @@ ctnetlink_stat_ct_cpu(struct sock *ctnl, struct sk_buff *skb,
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		struct netlink_dump_control c = {
 			.dump = ctnetlink_ct_stat_cpu_dump,
+			.done = netlink_dump_done,
+			.module = THIS_MODULE,
 		};
 		return netlink_dump_start(ctnl, skb, nlh, &c);
 	}
@@ -2141,6 +2145,7 @@ static int ctnetlink_exp_done(struct netlink_callback *cb)
 {
 	if (cb->args[1])
 		nf_ct_expect_put((struct nf_conntrack_expect *)cb->args[1]);
+	netlink_dump_done(cb);
 	return 0;
 }
I should do return netlink_dump_done here.
I will reset this patchset.

Re: [patch v2 04/11] nf_conntrack_netlink: pass nf_conntrack_netlink module to netlink_dump_start

From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: 2012-09-26 09:26:32

On Wed, Sep 26, 2012 at 04:41:21PM +0800, Gao feng wrote:
quoted hunk
use proper netlink_dump_control.done and .module to avoid panic.

Signed-off-by: Gao feng <redacted>
---
 net/netfilter/nf_conntrack_netlink.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 9807f32..509a257 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -706,6 +706,7 @@ static int ctnetlink_done(struct netlink_callback *cb)
 		nf_ct_put((struct nf_conn *)cb->args[1]);
 	if (cb->data)
 		kfree(cb->data);
+	netlink_dump_done(cb);
I think you can call netlink_dump_done from af_netlink.c:

static int netlink_dump(struct sock *sk) 
        ...
        if (cb->done) {
                cb->done(cb);
                netlink_dump_done(...);
        }

Thus, you don't need to change netlink_dump_control in every netlink
subsystem.
quoted hunk
 	return 0;
 }
 
@@ -1022,6 +1023,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
 		struct netlink_dump_control c = {
 			.dump = ctnetlink_dump_table,
 			.done = ctnetlink_done,
+			.module = THIS_MODULE,
You can do something similar to:

9f00d97 netlink: hide struct module parameter in netlink_kernel_create

by definiting netlink_dump_start as static inline and using
THIS_MODULE from there.

If I'm not missing anything, with those two changes, you will not need
to modify any caller and it will result one single patch.

Re: [patch v2 04/11] nf_conntrack_netlink: pass nf_conntrack_netlink module to netlink_dump_start

From: Gao feng <hidden>
Date: 2012-09-26 09:42:37

Hi Pablo:

于 2012年09月26日 17:26, Pablo Neira Ayuso 写道:
On Wed, Sep 26, 2012 at 04:41:21PM +0800, Gao feng wrote:
quoted
use proper netlink_dump_control.done and .module to avoid panic.

Signed-off-by: Gao feng <redacted>
---
 net/netfilter/nf_conntrack_netlink.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 9807f32..509a257 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -706,6 +706,7 @@ static int ctnetlink_done(struct netlink_callback *cb)
 		nf_ct_put((struct nf_conn *)cb->args[1]);
 	if (cb->data)
 		kfree(cb->data);
+	netlink_dump_done(cb);
I think you can call netlink_dump_done from af_netlink.c:

static int netlink_dump(struct sock *sk) 
        ...
        if (cb->done) {
                cb->done(cb);
                netlink_dump_done(...);
        }

Thus, you don't need to change netlink_dump_control in every netlink
subsystem.
because cb->done is called by netlink_sock_destruct too,it's very usefully
when userspace program only send dump request to kernel without reading
data from kernel.
quoted
 	return 0;
 }
 
@@ -1022,6 +1023,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
 		struct netlink_dump_control c = {
 			.dump = ctnetlink_dump_table,
 			.done = ctnetlink_done,
+			.module = THIS_MODULE,
You can do something similar to:

9f00d97 netlink: hide struct module parameter in netlink_kernel_create

by definiting netlink_dump_start as static inline and using
THIS_MODULE from there.

If I'm not missing anything, with those two changes, you will not need
to modify any caller and it will result one single patch.
You can see the patch [11/11], THIS_MODULE in infiniband/core/cma.c
means module rdma_cm,but we call netlink_dump_start in infiniband/core/netlink.c

we should make sure the cb.moudle point to the module which cb.dump belongs to.
we can call netlink_dump_start to set cb->dump everywhere, so I think we still
need to pass struct module to the netlink_callback.

thanks for your comments!

Re: [patch v2 04/11] nf_conntrack_netlink: pass nf_conntrack_netlink module to netlink_dump_start

From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: 2012-09-26 09:58:37

On Wed, Sep 26, 2012 at 05:42:31PM +0800, Gao feng wrote:
Hi Pablo:

于 2012年09月26日 17:26, Pablo Neira Ayuso 写道:
quoted
On Wed, Sep 26, 2012 at 04:41:21PM +0800, Gao feng wrote:
quoted
use proper netlink_dump_control.done and .module to avoid panic.

Signed-off-by: Gao feng <redacted>
---
 net/netfilter/nf_conntrack_netlink.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 9807f32..509a257 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -706,6 +706,7 @@ static int ctnetlink_done(struct netlink_callback *cb)
 		nf_ct_put((struct nf_conn *)cb->args[1]);
 	if (cb->data)
 		kfree(cb->data);
+	netlink_dump_done(cb);
I think you can call netlink_dump_done from af_netlink.c:

static int netlink_dump(struct sock *sk) 
        ...
        if (cb->done) {
                cb->done(cb);
                netlink_dump_done(...);
        }

Thus, you don't need to change netlink_dump_control in every netlink
subsystem.
because cb->done is called by netlink_sock_destruct too,it's very usefully
when userspace program only send dump request to kernel without reading
data from kernel.
Then add that to netlink_sock_destruct as well. If possible, I prefer
if this remains in the netlink core to avoid leaking module refcount
if you forget to call netlink_dump_done.
quoted
quoted
 	return 0;
 }
 
@@ -1022,6 +1023,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
 		struct netlink_dump_control c = {
 			.dump = ctnetlink_dump_table,
 			.done = ctnetlink_done,
+			.module = THIS_MODULE,
You can do something similar to:

9f00d97 netlink: hide struct module parameter in netlink_kernel_create

by definiting netlink_dump_start as static inline and using
THIS_MODULE from there.

If I'm not missing anything, with those two changes, you will not need
to modify any caller and it will result one single patch.
You can see the patch [11/11], THIS_MODULE in infiniband/core/cma.c
means module rdma_cm,but we call netlink_dump_start in infiniband/core/netlink.c
You can still use __netlink_dump_start for that case, which allows you
to specify a custom struct module * parameter. But for most cases,
netlink_dump_start (which hides THIS_MODULE) should be fine.
we should make sure the cb.moudle point to the module which cb.dump belongs to.
we can call netlink_dump_start to set cb->dump everywhere, so I think we still
need to pass struct module to the netlink_callback.

thanks for your comments!
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Re: [patch v2 04/11] nf_conntrack_netlink: pass nf_conntrack_netlink module to netlink_dump_start

From: Gao feng <hidden>
Date: 2012-09-26 12:35:53

于 2012年09月26日 17:58, Pablo Neira Ayuso 写道:
On Wed, Sep 26, 2012 at 05:42:31PM +0800, Gao feng wrote:
quoted
Hi Pablo:

于 2012年09月26日 17:26, Pablo Neira Ayuso 写道:
quoted
On Wed, Sep 26, 2012 at 04:41:21PM +0800, Gao feng wrote:
quoted
use proper netlink_dump_control.done and .module to avoid panic.

Signed-off-by: Gao feng <redacted>
---
 net/netfilter/nf_conntrack_netlink.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 9807f32..509a257 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -706,6 +706,7 @@ static int ctnetlink_done(struct netlink_callback *cb)
 		nf_ct_put((struct nf_conn *)cb->args[1]);
 	if (cb->data)
 		kfree(cb->data);
+	netlink_dump_done(cb);
I think you can call netlink_dump_done from af_netlink.c:

static int netlink_dump(struct sock *sk) 
        ...
        if (cb->done) {
                cb->done(cb);
                netlink_dump_done(...);
        }

Thus, you don't need to change netlink_dump_control in every netlink
subsystem.
because cb->done is called by netlink_sock_destruct too,it's very usefully
when userspace program only send dump request to kernel without reading
data from kernel.
Then add that to netlink_sock_destruct as well. If possible, I prefer
if this remains in the netlink core to avoid leaking module refcount
if you forget to call netlink_dump_done.
make sense,I will update it in next version.
Thanks!
quoted
quoted
quoted
 	return 0;
 }
 
@@ -1022,6 +1023,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
 		struct netlink_dump_control c = {
 			.dump = ctnetlink_dump_table,
 			.done = ctnetlink_done,
+			.module = THIS_MODULE,
You can do something similar to:

9f00d97 netlink: hide struct module parameter in netlink_kernel_create

by definiting netlink_dump_start as static inline and using
THIS_MODULE from there.

If I'm not missing anything, with those two changes, you will not need
to modify any caller and it will result one single patch.
You can see the patch [11/11], THIS_MODULE in infiniband/core/cma.c
means module rdma_cm,but we call netlink_dump_start in infiniband/core/netlink.c
You can still use __netlink_dump_start for that case, which allows you
to specify a custom struct module * parameter. But for most cases,
netlink_dump_start (which hides THIS_MODULE) should be fine.
I don't know how to deal with module_put in this way.
and I think my  way is simple enough.

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help