2012-09-26 08:46:21

by Gao feng

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

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 <[email protected]>
---
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


2012-09-26 08:46:17

by Gao feng

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

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

Signed-off-by: Gao feng <[email protected]>
---
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

2012-09-26 08:46:23

by Gao feng

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

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

Signed-off-by: Gao feng <[email protected]>
Cc: Herbert Xu <[email protected]>
---
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

2012-09-26 08:46:17

by Gao feng

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

set netlink_dump_control.done and .module to avoid panic.

Signed-off-by: Gao feng <[email protected]>
---
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

2012-09-26 08:41:26

by Gao feng

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

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

Signed-off-by: Gao feng <[email protected]>
---
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

2012-09-26 08:41:19

by Gao feng

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

set netlink_dump_control.done and .module to avoid panic.

Signed-off-by: Gao feng <[email protected]>
---
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


2012-09-26 08:41:21

by Gao feng

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

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

Signed-off-by: Gao feng <[email protected]>
---
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


2012-09-26 09:25:28

by Gao feng

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

于 2012年09月26日 16:41, Gao feng 写道:
> use proper netlink_dump_control.done and .module to avoid panic.
>
> Signed-off-by: Gao feng <[email protected]>
> ---
> 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.

2012-09-26 09:26:32

by Pablo Neira Ayuso

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

On Wed, Sep 26, 2012 at 04:41:21PM +0800, Gao feng wrote:
> use proper netlink_dump_control.done and .module to avoid panic.
>
> Signed-off-by: Gao feng <[email protected]>
> ---
> 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.

> 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.

2012-09-26 09:42:37

by Gao feng

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

Hi Pablo:

于 2012年09月26日 17:26, Pablo Neira Ayuso 写道:
> On Wed, Sep 26, 2012 at 04:41:21PM +0800, Gao feng wrote:
>> use proper netlink_dump_control.done and .module to avoid panic.
>>
>> Signed-off-by: Gao feng <[email protected]>
>> ---
>> 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.

>
>> 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!

2012-09-26 09:58:37

by Pablo Neira Ayuso

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

On Wed, Sep 26, 2012 at 05:42:31PM +0800, Gao feng wrote:
> Hi Pablo:
>
> 于 2012年09月26日 17:26, Pablo Neira Ayuso 写道:
> > On Wed, Sep 26, 2012 at 04:41:21PM +0800, Gao feng wrote:
> >> use proper netlink_dump_control.done and .module to avoid panic.
> >>
> >> Signed-off-by: Gao feng <[email protected]>
> >> ---
> >> 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.

> >
> >> 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 [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2012-09-26 12:35:53

by Gao feng

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

于 2012年09月26日 17:58, Pablo Neira Ayuso 写道:
> On Wed, Sep 26, 2012 at 05:42:31PM +0800, Gao feng wrote:
>> Hi Pablo:
>>
>> 于 2012年09月26日 17:26, Pablo Neira Ayuso 写道:
>>> On Wed, Sep 26, 2012 at 04:41:21PM +0800, Gao feng wrote:
>>>> use proper netlink_dump_control.done and .module to avoid panic.
>>>>
>>>> Signed-off-by: Gao feng <gao[email protected]>
>>>> ---
>>>> 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!

>
>>>
>>>> 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.

2012-09-26 15:04:30

by Pablo Neira Ayuso

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

On Wed, Sep 26, 2012 at 08:35:53PM +0800, Gao feng wrote:
> 于 2012年09月26日 17:58, Pablo Neira Ayuso 写道:
> > On Wed, Sep 26, 2012 at 05:42:31PM +0800, Gao feng wrote:
> >> Hi Pablo:
> >>
> >> 于 2012年09月26日 17:26, Pablo Neira Ayuso 写道:
> >>> On Wed, Sep 26, 2012 at 04:41:21PM +0800, Gao feng wrote:
> >>>> use proper netlink_dump_control.done and .module to avoid panic.
> >>>>
> >>>> Signed-off-by: Gao feng <[email protected]>
> >>>> ---
> >>>> 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!

Great. Remove also netlink_dump_done and just use module_put instead
after cb->done. That new function you added is so small that there is
no way to justify its addition.

> >
> >>>
> >>>> 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.

Not sure what problem with module_put you're refering to.

I think you can make this patchset way smaller with the change I'm
proposing.

2012-09-27 00:14:28

by Gao feng

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

于 2012年09月26日 23:04, Pablo Neira Ayuso 写道:
> On Wed, Sep 26, 2012 at 08:35:53PM +0800, Gao feng wrote:
>> 于 2012年09月26日 17:58, Pablo Neira Ayuso 写道:
>>> On Wed, Sep 26, 2012 at 05:42:31PM +0800, Gao feng wrote:
>>>> Hi Pablo:
>>>>
>>>> 于 2012年09月26日 17:26, Pablo Neira Ayuso 写道:
>>>>> On Wed, Sep 26, 2012 at 04:41:21PM +0800, Gao feng wrote:
>>>>>> use proper netlink_dump_control.done and .module to avoid panic.
>>>>>>
>>>>>> Signed-off-by: Gao feng <[email protected]>
>>>>>> ---
>>>>>> 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!
>
> Great. Remove also netlink_dump_done and just use module_put instead
> after cb->done. That new function you added is so small that there is
> no way to justify its addition.
>
>>>
>>>>>
>>>>>> 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.
>
> Not sure what problem with module_put you're refering to.
>

forget this,I'm wrong.

> I think you can make this patchset way smaller with the change I'm
> proposing.
>

I know,but I choose simple and directviewing, not smaller.
I think these two function will make people confuse.

Thanks!