diff options
author | Patrick McHardy <kaber@trash.net> | 2007-04-20 17:14:21 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-26 01:29:03 -0400 |
commit | af65bdfce98d7965fbe93a48b8128444a2eea024 (patch) | |
tree | e6ac5ff82a0d5067213135cdf049b912b02e824d | |
parent | b076deb8498e26c9aa2f44046fe5e9936ae2fb5a (diff) |
[NETLINK]: Switch cb_lock spinlock to mutex and allow to override it
Switch cb_lock to mutex and allow netlink kernel users to override it
with a subsystem specific mutex for consistent locking in dump callbacks.
All netlink_dump_start users have been audited not to rely on any
side-effects of the previously used spinlock.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/connector/connector.c | 2 | ||||
-rw-r--r-- | drivers/scsi/scsi_netlink.c | 3 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 2 | ||||
-rw-r--r-- | fs/ecryptfs/netlink.c | 2 | ||||
-rw-r--r-- | include/linux/netlink.h | 5 | ||||
-rw-r--r-- | kernel/audit.c | 2 | ||||
-rw-r--r-- | lib/kobject_uevent.c | 2 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_ulog.c | 2 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 2 | ||||
-rw-r--r-- | net/decnet/netfilter/dn_rtmsg.c | 2 | ||||
-rw-r--r-- | net/ipv4/fib_frontend.c | 3 | ||||
-rw-r--r-- | net/ipv4/inet_diag.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_queue.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_ULOG.c | 2 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_queue.c | 2 | ||||
-rw-r--r-- | net/netfilter/nfnetlink.c | 2 | ||||
-rw-r--r-- | net/netlink/af_netlink.c | 38 | ||||
-rw-r--r-- | net/netlink/genetlink.c | 2 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 2 | ||||
-rw-r--r-- | security/selinux/netlink.c | 2 |
20 files changed, 47 insertions, 34 deletions
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index 7f9c4fb7e5b0..a7b9e9bb3e8d 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c | |||
@@ -448,7 +448,7 @@ static int __devinit cn_init(void) | |||
448 | 448 | ||
449 | dev->nls = netlink_kernel_create(NETLINK_CONNECTOR, | 449 | dev->nls = netlink_kernel_create(NETLINK_CONNECTOR, |
450 | CN_NETLINK_USERS + 0xf, | 450 | CN_NETLINK_USERS + 0xf, |
451 | dev->input, THIS_MODULE); | 451 | dev->input, NULL, THIS_MODULE); |
452 | if (!dev->nls) | 452 | if (!dev->nls) |
453 | return -EIO; | 453 | return -EIO; |
454 | 454 | ||
diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c index 45646a285244..4bf9aa547c78 100644 --- a/drivers/scsi/scsi_netlink.c +++ b/drivers/scsi/scsi_netlink.c | |||
@@ -168,7 +168,8 @@ scsi_netlink_init(void) | |||
168 | } | 168 | } |
169 | 169 | ||
170 | scsi_nl_sock = netlink_kernel_create(NETLINK_SCSITRANSPORT, | 170 | scsi_nl_sock = netlink_kernel_create(NETLINK_SCSITRANSPORT, |
171 | SCSI_NL_GRP_CNT, scsi_nl_rcv, THIS_MODULE); | 171 | SCSI_NL_GRP_CNT, scsi_nl_rcv, NULL, |
172 | THIS_MODULE); | ||
172 | if (!scsi_nl_sock) { | 173 | if (!scsi_nl_sock) { |
173 | printk(KERN_ERR "%s: register of recieve handler failed\n", | 174 | printk(KERN_ERR "%s: register of recieve handler failed\n", |
174 | __FUNCTION__); | 175 | __FUNCTION__); |
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 10590cd7e9ed..aabaa0576ab4 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -1435,7 +1435,7 @@ static __init int iscsi_transport_init(void) | |||
1435 | if (err) | 1435 | if (err) |
1436 | goto unregister_conn_class; | 1436 | goto unregister_conn_class; |
1437 | 1437 | ||
1438 | nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx, | 1438 | nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx, NULL, |
1439 | THIS_MODULE); | 1439 | THIS_MODULE); |
1440 | if (!nls) { | 1440 | if (!nls) { |
1441 | err = -ENOBUFS; | 1441 | err = -ENOBUFS; |
diff --git a/fs/ecryptfs/netlink.c b/fs/ecryptfs/netlink.c index 8405d216a5fc..fe9186312d7c 100644 --- a/fs/ecryptfs/netlink.c +++ b/fs/ecryptfs/netlink.c | |||
@@ -229,7 +229,7 @@ int ecryptfs_init_netlink(void) | |||
229 | 229 | ||
230 | ecryptfs_nl_sock = netlink_kernel_create(NETLINK_ECRYPTFS, 0, | 230 | ecryptfs_nl_sock = netlink_kernel_create(NETLINK_ECRYPTFS, 0, |
231 | ecryptfs_receive_nl_message, | 231 | ecryptfs_receive_nl_message, |
232 | THIS_MODULE); | 232 | NULL, THIS_MODULE); |
233 | if (!ecryptfs_nl_sock) { | 233 | if (!ecryptfs_nl_sock) { |
234 | rc = -EIO; | 234 | rc = -EIO; |
235 | ecryptfs_printk(KERN_ERR, "Failed to create netlink socket\n"); | 235 | ecryptfs_printk(KERN_ERR, "Failed to create netlink socket\n"); |
diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 0d11f6a7389c..f41688f56632 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h | |||
@@ -157,7 +157,10 @@ struct netlink_skb_parms | |||
157 | #define NETLINK_CREDS(skb) (&NETLINK_CB((skb)).creds) | 157 | #define NETLINK_CREDS(skb) (&NETLINK_CB((skb)).creds) |
158 | 158 | ||
159 | 159 | ||
160 | extern struct sock *netlink_kernel_create(int unit, unsigned int groups, void (*input)(struct sock *sk, int len), struct module *module); | 160 | extern struct sock *netlink_kernel_create(int unit, unsigned int groups, |
161 | void (*input)(struct sock *sk, int len), | ||
162 | struct mutex *cb_mutex, | ||
163 | struct module *module); | ||
161 | extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err); | 164 | extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err); |
162 | extern int netlink_has_listeners(struct sock *sk, unsigned int group); | 165 | extern int netlink_has_listeners(struct sock *sk, unsigned int group); |
163 | extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock); | 166 | extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock); |
diff --git a/kernel/audit.c b/kernel/audit.c index 80a7457dadbf..4e9d20829681 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -795,7 +795,7 @@ static int __init audit_init(void) | |||
795 | printk(KERN_INFO "audit: initializing netlink socket (%s)\n", | 795 | printk(KERN_INFO "audit: initializing netlink socket (%s)\n", |
796 | audit_default ? "enabled" : "disabled"); | 796 | audit_default ? "enabled" : "disabled"); |
797 | audit_sock = netlink_kernel_create(NETLINK_AUDIT, 0, audit_receive, | 797 | audit_sock = netlink_kernel_create(NETLINK_AUDIT, 0, audit_receive, |
798 | THIS_MODULE); | 798 | NULL, THIS_MODULE); |
799 | if (!audit_sock) | 799 | if (!audit_sock) |
800 | audit_panic("cannot initialize netlink socket"); | 800 | audit_panic("cannot initialize netlink socket"); |
801 | else | 801 | else |
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index 84272ed77f03..82fc1794b691 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c | |||
@@ -293,7 +293,7 @@ EXPORT_SYMBOL_GPL(add_uevent_var); | |||
293 | static int __init kobject_uevent_init(void) | 293 | static int __init kobject_uevent_init(void) |
294 | { | 294 | { |
295 | uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, 1, NULL, | 295 | uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, 1, NULL, |
296 | THIS_MODULE); | 296 | NULL, THIS_MODULE); |
297 | 297 | ||
298 | if (!uevent_sock) { | 298 | if (!uevent_sock) { |
299 | printk(KERN_ERR | 299 | printk(KERN_ERR |
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index 8b84cd40279e..9411db625917 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c | |||
@@ -302,7 +302,7 @@ static int __init ebt_ulog_init(void) | |||
302 | } | 302 | } |
303 | 303 | ||
304 | ebtulognl = netlink_kernel_create(NETLINK_NFLOG, EBT_ULOG_MAXNLGROUPS, | 304 | ebtulognl = netlink_kernel_create(NETLINK_NFLOG, EBT_ULOG_MAXNLGROUPS, |
305 | NULL, THIS_MODULE); | 305 | NULL, NULL, THIS_MODULE); |
306 | if (!ebtulognl) | 306 | if (!ebtulognl) |
307 | ret = -ENOMEM; | 307 | ret = -ENOMEM; |
308 | else if ((ret = ebt_register_watcher(&ulog))) | 308 | else if ((ret = ebt_register_watcher(&ulog))) |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 5266df337051..648a7b6d15df 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -972,7 +972,7 @@ void __init rtnetlink_init(void) | |||
972 | panic("rtnetlink_init: cannot allocate rta_buf\n"); | 972 | panic("rtnetlink_init: cannot allocate rta_buf\n"); |
973 | 973 | ||
974 | rtnl = netlink_kernel_create(NETLINK_ROUTE, RTNLGRP_MAX, rtnetlink_rcv, | 974 | rtnl = netlink_kernel_create(NETLINK_ROUTE, RTNLGRP_MAX, rtnetlink_rcv, |
975 | THIS_MODULE); | 975 | NULL, THIS_MODULE); |
976 | if (rtnl == NULL) | 976 | if (rtnl == NULL) |
977 | panic("rtnetlink_init: cannot initialize rtnetlink\n"); | 977 | panic("rtnetlink_init: cannot initialize rtnetlink\n"); |
978 | netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV); | 978 | netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV); |
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c index 2ee47bab6938..696234688cf6 100644 --- a/net/decnet/netfilter/dn_rtmsg.c +++ b/net/decnet/netfilter/dn_rtmsg.c | |||
@@ -138,7 +138,7 @@ static int __init dn_rtmsg_init(void) | |||
138 | int rv = 0; | 138 | int rv = 0; |
139 | 139 | ||
140 | dnrmg = netlink_kernel_create(NETLINK_DNRTMSG, DNRNG_NLGRP_MAX, | 140 | dnrmg = netlink_kernel_create(NETLINK_DNRTMSG, DNRNG_NLGRP_MAX, |
141 | dnrmg_receive_user_sk, THIS_MODULE); | 141 | dnrmg_receive_user_sk, NULL, THIS_MODULE); |
142 | if (dnrmg == NULL) { | 142 | if (dnrmg == NULL) { |
143 | printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket"); | 143 | printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket"); |
144 | return -ENOMEM; | 144 | return -ENOMEM; |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 5bf718a3e49b..953dd458c239 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -827,7 +827,8 @@ static void nl_fib_input(struct sock *sk, int len) | |||
827 | 827 | ||
828 | static void nl_fib_lookup_init(void) | 828 | static void nl_fib_lookup_init(void) |
829 | { | 829 | { |
830 | netlink_kernel_create(NETLINK_FIB_LOOKUP, 0, nl_fib_input, THIS_MODULE); | 830 | netlink_kernel_create(NETLINK_FIB_LOOKUP, 0, nl_fib_input, NULL, |
831 | THIS_MODULE); | ||
831 | } | 832 | } |
832 | 833 | ||
833 | static void fib_disable_ip(struct net_device *dev, int force) | 834 | static void fib_disable_ip(struct net_device *dev, int force) |
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 0148f0e34ceb..dbeacd8b0f90 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -893,7 +893,7 @@ static int __init inet_diag_init(void) | |||
893 | goto out; | 893 | goto out; |
894 | 894 | ||
895 | idiagnl = netlink_kernel_create(NETLINK_INET_DIAG, 0, inet_diag_rcv, | 895 | idiagnl = netlink_kernel_create(NETLINK_INET_DIAG, 0, inet_diag_rcv, |
896 | THIS_MODULE); | 896 | NULL, THIS_MODULE); |
897 | if (idiagnl == NULL) | 897 | if (idiagnl == NULL) |
898 | goto out_free_table; | 898 | goto out_free_table; |
899 | err = 0; | 899 | err = 0; |
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 0d72693869e6..702d94db19b9 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c | |||
@@ -668,7 +668,7 @@ static int __init ip_queue_init(void) | |||
668 | 668 | ||
669 | netlink_register_notifier(&ipq_nl_notifier); | 669 | netlink_register_notifier(&ipq_nl_notifier); |
670 | ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk, | 670 | ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk, |
671 | THIS_MODULE); | 671 | NULL, THIS_MODULE); |
672 | if (ipqnl == NULL) { | 672 | if (ipqnl == NULL) { |
673 | printk(KERN_ERR "ip_queue: failed to create netlink socket\n"); | 673 | printk(KERN_ERR "ip_queue: failed to create netlink socket\n"); |
674 | goto cleanup_netlink_notifier; | 674 | goto cleanup_netlink_notifier; |
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index a2bcba70af50..23b607b33b32 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c | |||
@@ -420,7 +420,7 @@ static int __init ipt_ulog_init(void) | |||
420 | setup_timer(&ulog_buffers[i].timer, ulog_timer, i); | 420 | setup_timer(&ulog_buffers[i].timer, ulog_timer, i); |
421 | 421 | ||
422 | nflognl = netlink_kernel_create(NETLINK_NFLOG, ULOG_MAXNLGROUPS, NULL, | 422 | nflognl = netlink_kernel_create(NETLINK_NFLOG, ULOG_MAXNLGROUPS, NULL, |
423 | THIS_MODULE); | 423 | NULL, THIS_MODULE); |
424 | if (!nflognl) | 424 | if (!nflognl) |
425 | return -ENOMEM; | 425 | return -ENOMEM; |
426 | 426 | ||
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index bfae9fdc4668..0004db38af6d 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -657,7 +657,7 @@ static int __init ip6_queue_init(void) | |||
657 | struct proc_dir_entry *proc; | 657 | struct proc_dir_entry *proc; |
658 | 658 | ||
659 | netlink_register_notifier(&ipq_nl_notifier); | 659 | netlink_register_notifier(&ipq_nl_notifier); |
660 | ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk, | 660 | ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk, NULL, |
661 | THIS_MODULE); | 661 | THIS_MODULE); |
662 | if (ipqnl == NULL) { | 662 | if (ipqnl == NULL) { |
663 | printk(KERN_ERR "ip6_queue: failed to create netlink socket\n"); | 663 | printk(KERN_ERR "ip6_queue: failed to create netlink socket\n"); |
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index b0da853eabe0..8797e6953ef2 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
@@ -265,7 +265,7 @@ static int __init nfnetlink_init(void) | |||
265 | printk("Netfilter messages via NETLINK v%s.\n", nfversion); | 265 | printk("Netfilter messages via NETLINK v%s.\n", nfversion); |
266 | 266 | ||
267 | nfnl = netlink_kernel_create(NETLINK_NETFILTER, NFNLGRP_MAX, | 267 | nfnl = netlink_kernel_create(NETLINK_NETFILTER, NFNLGRP_MAX, |
268 | nfnetlink_rcv, THIS_MODULE); | 268 | nfnetlink_rcv, NULL, THIS_MODULE); |
269 | if (!nfnl) { | 269 | if (!nfnl) { |
270 | printk(KERN_ERR "cannot initialize nfnetlink!\n"); | 270 | printk(KERN_ERR "cannot initialize nfnetlink!\n"); |
271 | return -1; | 271 | return -1; |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 2cbf1682f63d..ec16c9b7b3bd 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include <linux/types.h> | 56 | #include <linux/types.h> |
57 | #include <linux/audit.h> | 57 | #include <linux/audit.h> |
58 | #include <linux/selinux.h> | 58 | #include <linux/selinux.h> |
59 | #include <linux/mutex.h> | ||
59 | 60 | ||
60 | #include <net/sock.h> | 61 | #include <net/sock.h> |
61 | #include <net/scm.h> | 62 | #include <net/scm.h> |
@@ -76,7 +77,8 @@ struct netlink_sock { | |||
76 | unsigned long state; | 77 | unsigned long state; |
77 | wait_queue_head_t wait; | 78 | wait_queue_head_t wait; |
78 | struct netlink_callback *cb; | 79 | struct netlink_callback *cb; |
79 | spinlock_t cb_lock; | 80 | struct mutex *cb_mutex; |
81 | struct mutex cb_def_mutex; | ||
80 | void (*data_ready)(struct sock *sk, int bytes); | 82 | void (*data_ready)(struct sock *sk, int bytes); |
81 | struct module *module; | 83 | struct module *module; |
82 | }; | 84 | }; |
@@ -108,6 +110,7 @@ struct netlink_table { | |||
108 | unsigned long *listeners; | 110 | unsigned long *listeners; |
109 | unsigned int nl_nonroot; | 111 | unsigned int nl_nonroot; |
110 | unsigned int groups; | 112 | unsigned int groups; |
113 | struct mutex *cb_mutex; | ||
111 | struct module *module; | 114 | struct module *module; |
112 | int registered; | 115 | int registered; |
113 | }; | 116 | }; |
@@ -370,7 +373,8 @@ static struct proto netlink_proto = { | |||
370 | .obj_size = sizeof(struct netlink_sock), | 373 | .obj_size = sizeof(struct netlink_sock), |
371 | }; | 374 | }; |
372 | 375 | ||
373 | static int __netlink_create(struct socket *sock, int protocol) | 376 | static int __netlink_create(struct socket *sock, struct mutex *cb_mutex, |
377 | int protocol) | ||
374 | { | 378 | { |
375 | struct sock *sk; | 379 | struct sock *sk; |
376 | struct netlink_sock *nlk; | 380 | struct netlink_sock *nlk; |
@@ -384,7 +388,8 @@ static int __netlink_create(struct socket *sock, int protocol) | |||
384 | sock_init_data(sock, sk); | 388 | sock_init_data(sock, sk); |
385 | 389 | ||
386 | nlk = nlk_sk(sk); | 390 | nlk = nlk_sk(sk); |
387 | spin_lock_init(&nlk->cb_lock); | 391 | nlk->cb_mutex = cb_mutex ? : &nlk->cb_def_mutex; |
392 | mutex_init(nlk->cb_mutex); | ||
388 | init_waitqueue_head(&nlk->wait); | 393 | init_waitqueue_head(&nlk->wait); |
389 | 394 | ||
390 | sk->sk_destruct = netlink_sock_destruct; | 395 | sk->sk_destruct = netlink_sock_destruct; |
@@ -395,6 +400,7 @@ static int __netlink_create(struct socket *sock, int protocol) | |||
395 | static int netlink_create(struct socket *sock, int protocol) | 400 | static int netlink_create(struct socket *sock, int protocol) |
396 | { | 401 | { |
397 | struct module *module = NULL; | 402 | struct module *module = NULL; |
403 | struct mutex *cb_mutex; | ||
398 | struct netlink_sock *nlk; | 404 | struct netlink_sock *nlk; |
399 | int err = 0; | 405 | int err = 0; |
400 | 406 | ||
@@ -417,9 +423,10 @@ static int netlink_create(struct socket *sock, int protocol) | |||
417 | if (nl_table[protocol].registered && | 423 | if (nl_table[protocol].registered && |
418 | try_module_get(nl_table[protocol].module)) | 424 | try_module_get(nl_table[protocol].module)) |
419 | module = nl_table[protocol].module; | 425 | module = nl_table[protocol].module; |
426 | cb_mutex = nl_table[protocol].cb_mutex; | ||
420 | netlink_unlock_table(); | 427 | netlink_unlock_table(); |
421 | 428 | ||
422 | if ((err = __netlink_create(sock, protocol)) < 0) | 429 | if ((err = __netlink_create(sock, cb_mutex, protocol)) < 0) |
423 | goto out_module; | 430 | goto out_module; |
424 | 431 | ||
425 | nlk = nlk_sk(sock->sk); | 432 | nlk = nlk_sk(sock->sk); |
@@ -444,14 +451,14 @@ static int netlink_release(struct socket *sock) | |||
444 | sock_orphan(sk); | 451 | sock_orphan(sk); |
445 | nlk = nlk_sk(sk); | 452 | nlk = nlk_sk(sk); |
446 | 453 | ||
447 | spin_lock(&nlk->cb_lock); | 454 | mutex_lock(nlk->cb_mutex); |
448 | if (nlk->cb) { | 455 | if (nlk->cb) { |
449 | if (nlk->cb->done) | 456 | if (nlk->cb->done) |
450 | nlk->cb->done(nlk->cb); | 457 | nlk->cb->done(nlk->cb); |
451 | netlink_destroy_callback(nlk->cb); | 458 | netlink_destroy_callback(nlk->cb); |
452 | nlk->cb = NULL; | 459 | nlk->cb = NULL; |
453 | } | 460 | } |
454 | spin_unlock(&nlk->cb_lock); | 461 | mutex_unlock(nlk->cb_mutex); |
455 | 462 | ||
456 | /* OK. Socket is unlinked, and, therefore, | 463 | /* OK. Socket is unlinked, and, therefore, |
457 | no new packets will arrive */ | 464 | no new packets will arrive */ |
@@ -1266,7 +1273,7 @@ static void netlink_data_ready(struct sock *sk, int len) | |||
1266 | struct sock * | 1273 | struct sock * |
1267 | netlink_kernel_create(int unit, unsigned int groups, | 1274 | netlink_kernel_create(int unit, unsigned int groups, |
1268 | void (*input)(struct sock *sk, int len), | 1275 | void (*input)(struct sock *sk, int len), |
1269 | struct module *module) | 1276 | struct mutex *cb_mutex, struct module *module) |
1270 | { | 1277 | { |
1271 | struct socket *sock; | 1278 | struct socket *sock; |
1272 | struct sock *sk; | 1279 | struct sock *sk; |
@@ -1281,7 +1288,7 @@ netlink_kernel_create(int unit, unsigned int groups, | |||
1281 | if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock)) | 1288 | if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock)) |
1282 | return NULL; | 1289 | return NULL; |
1283 | 1290 | ||
1284 | if (__netlink_create(sock, unit) < 0) | 1291 | if (__netlink_create(sock, cb_mutex, unit) < 0) |
1285 | goto out_sock_release; | 1292 | goto out_sock_release; |
1286 | 1293 | ||
1287 | if (groups < 32) | 1294 | if (groups < 32) |
@@ -1305,6 +1312,7 @@ netlink_kernel_create(int unit, unsigned int groups, | |||
1305 | netlink_table_grab(); | 1312 | netlink_table_grab(); |
1306 | nl_table[unit].groups = groups; | 1313 | nl_table[unit].groups = groups; |
1307 | nl_table[unit].listeners = listeners; | 1314 | nl_table[unit].listeners = listeners; |
1315 | nl_table[unit].cb_mutex = cb_mutex; | ||
1308 | nl_table[unit].module = module; | 1316 | nl_table[unit].module = module; |
1309 | nl_table[unit].registered = 1; | 1317 | nl_table[unit].registered = 1; |
1310 | netlink_table_ungrab(); | 1318 | netlink_table_ungrab(); |
@@ -1347,7 +1355,7 @@ static int netlink_dump(struct sock *sk) | |||
1347 | if (!skb) | 1355 | if (!skb) |
1348 | goto errout; | 1356 | goto errout; |
1349 | 1357 | ||
1350 | spin_lock(&nlk->cb_lock); | 1358 | mutex_lock(nlk->cb_mutex); |
1351 | 1359 | ||
1352 | cb = nlk->cb; | 1360 | cb = nlk->cb; |
1353 | if (cb == NULL) { | 1361 | if (cb == NULL) { |
@@ -1358,7 +1366,7 @@ static int netlink_dump(struct sock *sk) | |||
1358 | len = cb->dump(skb, cb); | 1366 | len = cb->dump(skb, cb); |
1359 | 1367 | ||
1360 | if (len > 0) { | 1368 | if (len > 0) { |
1361 | spin_unlock(&nlk->cb_lock); | 1369 | mutex_unlock(nlk->cb_mutex); |
1362 | skb_queue_tail(&sk->sk_receive_queue, skb); | 1370 | skb_queue_tail(&sk->sk_receive_queue, skb); |
1363 | sk->sk_data_ready(sk, len); | 1371 | sk->sk_data_ready(sk, len); |
1364 | return 0; | 1372 | return 0; |
@@ -1376,13 +1384,13 @@ static int netlink_dump(struct sock *sk) | |||
1376 | if (cb->done) | 1384 | if (cb->done) |
1377 | cb->done(cb); | 1385 | cb->done(cb); |
1378 | nlk->cb = NULL; | 1386 | nlk->cb = NULL; |
1379 | spin_unlock(&nlk->cb_lock); | 1387 | mutex_unlock(nlk->cb_mutex); |
1380 | 1388 | ||
1381 | netlink_destroy_callback(cb); | 1389 | netlink_destroy_callback(cb); |
1382 | return 0; | 1390 | return 0; |
1383 | 1391 | ||
1384 | errout_skb: | 1392 | errout_skb: |
1385 | spin_unlock(&nlk->cb_lock); | 1393 | mutex_unlock(nlk->cb_mutex); |
1386 | kfree_skb(skb); | 1394 | kfree_skb(skb); |
1387 | errout: | 1395 | errout: |
1388 | return err; | 1396 | return err; |
@@ -1414,15 +1422,15 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, | |||
1414 | } | 1422 | } |
1415 | nlk = nlk_sk(sk); | 1423 | nlk = nlk_sk(sk); |
1416 | /* A dump or destruction is in progress... */ | 1424 | /* A dump or destruction is in progress... */ |
1417 | spin_lock(&nlk->cb_lock); | 1425 | mutex_lock(nlk->cb_mutex); |
1418 | if (nlk->cb || sock_flag(sk, SOCK_DEAD)) { | 1426 | if (nlk->cb || sock_flag(sk, SOCK_DEAD)) { |
1419 | spin_unlock(&nlk->cb_lock); | 1427 | mutex_unlock(nlk->cb_mutex); |
1420 | netlink_destroy_callback(cb); | 1428 | netlink_destroy_callback(cb); |
1421 | sock_put(sk); | 1429 | sock_put(sk); |
1422 | return -EBUSY; | 1430 | return -EBUSY; |
1423 | } | 1431 | } |
1424 | nlk->cb = cb; | 1432 | nlk->cb = cb; |
1425 | spin_unlock(&nlk->cb_lock); | 1433 | mutex_unlock(nlk->cb_mutex); |
1426 | 1434 | ||
1427 | netlink_dump(sk); | 1435 | netlink_dump(sk); |
1428 | sock_put(sk); | 1436 | sock_put(sk); |
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index fac2e7a6dbe4..6e31234a4196 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
@@ -558,7 +558,7 @@ static int __init genl_init(void) | |||
558 | 558 | ||
559 | netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV); | 559 | netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV); |
560 | genl_sock = netlink_kernel_create(NETLINK_GENERIC, GENL_MAX_ID, | 560 | genl_sock = netlink_kernel_create(NETLINK_GENERIC, GENL_MAX_ID, |
561 | genl_rcv, THIS_MODULE); | 561 | genl_rcv, NULL, THIS_MODULE); |
562 | if (genl_sock == NULL) | 562 | if (genl_sock == NULL) |
563 | panic("GENL: Cannot initialize generic netlink\n"); | 563 | panic("GENL: Cannot initialize generic netlink\n"); |
564 | 564 | ||
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 2ff968373f1c..88659edc9b1a 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -2444,7 +2444,7 @@ static int __init xfrm_user_init(void) | |||
2444 | printk(KERN_INFO "Initializing XFRM netlink socket\n"); | 2444 | printk(KERN_INFO "Initializing XFRM netlink socket\n"); |
2445 | 2445 | ||
2446 | nlsk = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX, | 2446 | nlsk = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX, |
2447 | xfrm_netlink_rcv, THIS_MODULE); | 2447 | xfrm_netlink_rcv, NULL, THIS_MODULE); |
2448 | if (nlsk == NULL) | 2448 | if (nlsk == NULL) |
2449 | return -ENOMEM; | 2449 | return -ENOMEM; |
2450 | rcu_assign_pointer(xfrm_nl, nlsk); | 2450 | rcu_assign_pointer(xfrm_nl, nlsk); |
diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c index 33f2e064a682..f49046de63a2 100644 --- a/security/selinux/netlink.c +++ b/security/selinux/netlink.c | |||
@@ -104,7 +104,7 @@ void selnl_notify_policyload(u32 seqno) | |||
104 | 104 | ||
105 | static int __init selnl_init(void) | 105 | static int __init selnl_init(void) |
106 | { | 106 | { |
107 | selnl = netlink_kernel_create(NETLINK_SELINUX, SELNLGRP_MAX, NULL, | 107 | selnl = netlink_kernel_create(NETLINK_SELINUX, SELNLGRP_MAX, NULL, NULL, |
108 | THIS_MODULE); | 108 | THIS_MODULE); |
109 | if (selnl == NULL) | 109 | if (selnl == NULL) |
110 | panic("SELinux: Cannot create netlink socket."); | 110 | panic("SELinux: Cannot create netlink socket."); |