diff options
author | Gao feng <gaofeng@cn.fujitsu.com> | 2012-10-04 16:15:48 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-10-07 00:30:56 -0400 |
commit | 6dc878a8ca39e93f70c42f3dd7260bde10c1e0f1 (patch) | |
tree | 2549dc75d29ea1975611775b05921482caf75c04 /include/linux/netlink.h | |
parent | ed5062ddaa71e9f8b2b3aacc264428ce6da93d9e (diff) |
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 uses inet_diag_dump which belongs to module
inet_diag.
I search the codes and find many modules have the same problem. We
need to add a reference to the module which the cb->dump belongs to.
Thanks for all help from Stephen,Jan,Eric,Steffen and Pablo.
Change From v3:
change netlink_dump_start to inline,suggestion from Pablo and
Eric.
Change From v2:
delete netlink_dump_done,and call module_put in netlink_dump
and netlink_sock_destruct.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/netlink.h')
-rw-r--r-- | include/linux/netlink.h | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/include/linux/netlink.h b/include/linux/netlink.h index f80c56ac4d82..6d3af05c107c 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h | |||
@@ -245,6 +245,8 @@ struct netlink_callback { | |||
245 | struct netlink_callback *cb); | 245 | struct netlink_callback *cb); |
246 | int (*done)(struct netlink_callback *cb); | 246 | int (*done)(struct netlink_callback *cb); |
247 | void *data; | 247 | void *data; |
248 | /* the module that dump function belong to */ | ||
249 | struct module *module; | ||
248 | u16 family; | 250 | u16 family; |
249 | u16 min_dump_alloc; | 251 | u16 min_dump_alloc; |
250 | unsigned int prev_seq, seq; | 252 | unsigned int prev_seq, seq; |
@@ -262,14 +264,24 @@ __nlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, int type, int len, int fla | |||
262 | 264 | ||
263 | struct netlink_dump_control { | 265 | struct netlink_dump_control { |
264 | int (*dump)(struct sk_buff *skb, struct netlink_callback *); | 266 | int (*dump)(struct sk_buff *skb, struct netlink_callback *); |
265 | int (*done)(struct netlink_callback*); | 267 | int (*done)(struct netlink_callback *); |
266 | void *data; | 268 | void *data; |
269 | struct module *module; | ||
267 | u16 min_dump_alloc; | 270 | u16 min_dump_alloc; |
268 | }; | 271 | }; |
269 | 272 | ||
270 | extern int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, | 273 | extern int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, |
271 | const struct nlmsghdr *nlh, | 274 | const struct nlmsghdr *nlh, |
272 | struct netlink_dump_control *control); | 275 | struct netlink_dump_control *control); |
276 | static inline int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, | ||
277 | const struct nlmsghdr *nlh, | ||
278 | struct netlink_dump_control *control) | ||
279 | { | ||
280 | if (!control->module) | ||
281 | control->module = THIS_MODULE; | ||
282 | |||
283 | return __netlink_dump_start(ssk, skb, nlh, control); | ||
284 | } | ||
273 | 285 | ||
274 | #endif /* __KERNEL__ */ | 286 | #endif /* __KERNEL__ */ |
275 | 287 | ||