Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit af65bdf

Browse files
kaberDavid S. Miller
authored andcommitted
[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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b076deb commit af65bdf

File tree

20 files changed

+47
-34
lines changed

20 files changed

+47
-34
lines changed

drivers/connector/connector.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ static int __devinit cn_init(void)
448448

449449
dev->nls = netlink_kernel_create(NETLINK_CONNECTOR,
450450
CN_NETLINK_USERS + 0xf,
451-
dev->input, THIS_MODULE);
451+
dev->input, NULL, THIS_MODULE);
452452
if (!dev->nls)
453453
return -EIO;
454454

drivers/scsi/scsi_netlink.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ scsi_netlink_init(void)
168168
}
169169

170170
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);
172173
if (!scsi_nl_sock) {
173174
printk(KERN_ERR "%s: register of recieve handler failed\n",
174175
__FUNCTION__);

drivers/scsi/scsi_transport_iscsi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1435,7 +1435,7 @@ static __init int iscsi_transport_init(void)
14351435
if (err)
14361436
goto unregister_conn_class;
14371437

1438-
nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx,
1438+
nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx, NULL,
14391439
THIS_MODULE);
14401440
if (!nls) {
14411441
err = -ENOBUFS;

fs/ecryptfs/netlink.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ int ecryptfs_init_netlink(void)
229229

230230
ecryptfs_nl_sock = netlink_kernel_create(NETLINK_ECRYPTFS, 0,
231231
ecryptfs_receive_nl_message,
232-
THIS_MODULE);
232+
NULL, THIS_MODULE);
233233
if (!ecryptfs_nl_sock) {
234234
rc = -EIO;
235235
ecryptfs_printk(KERN_ERR, "Failed to create netlink socket\n");

include/linux/netlink.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,10 @@ struct netlink_skb_parms
157157
#define NETLINK_CREDS(skb) (&NETLINK_CB((skb)).creds)
158158

159159

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);
161164
extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
162165
extern int netlink_has_listeners(struct sock *sk, unsigned int group);
163166
extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock);

kernel/audit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,7 @@ static int __init audit_init(void)
795795
printk(KERN_INFO "audit: initializing netlink socket (%s)\n",
796796
audit_default ? "enabled" : "disabled");
797797
audit_sock = netlink_kernel_create(NETLINK_AUDIT, 0, audit_receive,
798-
THIS_MODULE);
798+
NULL, THIS_MODULE);
799799
if (!audit_sock)
800800
audit_panic("cannot initialize netlink socket");
801801
else

lib/kobject_uevent.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ EXPORT_SYMBOL_GPL(add_uevent_var);
293293
static int __init kobject_uevent_init(void)
294294
{
295295
uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, 1, NULL,
296-
THIS_MODULE);
296+
NULL, THIS_MODULE);
297297

298298
if (!uevent_sock) {
299299
printk(KERN_ERR

net/bridge/netfilter/ebt_ulog.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ static int __init ebt_ulog_init(void)
302302
}
303303

304304
ebtulognl = netlink_kernel_create(NETLINK_NFLOG, EBT_ULOG_MAXNLGROUPS,
305-
NULL, THIS_MODULE);
305+
NULL, NULL, THIS_MODULE);
306306
if (!ebtulognl)
307307
ret = -ENOMEM;
308308
else if ((ret = ebt_register_watcher(&ulog)))

net/core/rtnetlink.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -972,7 +972,7 @@ void __init rtnetlink_init(void)
972972
panic("rtnetlink_init: cannot allocate rta_buf\n");
973973

974974
rtnl = netlink_kernel_create(NETLINK_ROUTE, RTNLGRP_MAX, rtnetlink_rcv,
975-
THIS_MODULE);
975+
NULL, THIS_MODULE);
976976
if (rtnl == NULL)
977977
panic("rtnetlink_init: cannot initialize rtnetlink\n");
978978
netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV);

net/decnet/netfilter/dn_rtmsg.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ static int __init dn_rtmsg_init(void)
138138
int rv = 0;
139139

140140
dnrmg = netlink_kernel_create(NETLINK_DNRTMSG, DNRNG_NLGRP_MAX,
141-
dnrmg_receive_user_sk, THIS_MODULE);
141+
dnrmg_receive_user_sk, NULL, THIS_MODULE);
142142
if (dnrmg == NULL) {
143143
printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket");
144144
return -ENOMEM;

net/ipv4/fib_frontend.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,8 @@ static void nl_fib_input(struct sock *sk, int len)
827827

828828
static void nl_fib_lookup_init(void)
829829
{
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);
831832
}
832833

833834
static void fib_disable_ip(struct net_device *dev, int force)

net/ipv4/inet_diag.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,7 @@ static int __init inet_diag_init(void)
893893
goto out;
894894

895895
idiagnl = netlink_kernel_create(NETLINK_INET_DIAG, 0, inet_diag_rcv,
896-
THIS_MODULE);
896+
NULL, THIS_MODULE);
897897
if (idiagnl == NULL)
898898
goto out_free_table;
899899
err = 0;

net/ipv4/netfilter/ip_queue.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ static int __init ip_queue_init(void)
668668

669669
netlink_register_notifier(&ipq_nl_notifier);
670670
ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk,
671-
THIS_MODULE);
671+
NULL, THIS_MODULE);
672672
if (ipqnl == NULL) {
673673
printk(KERN_ERR "ip_queue: failed to create netlink socket\n");
674674
goto cleanup_netlink_notifier;

net/ipv4/netfilter/ipt_ULOG.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ static int __init ipt_ulog_init(void)
420420
setup_timer(&ulog_buffers[i].timer, ulog_timer, i);
421421

422422
nflognl = netlink_kernel_create(NETLINK_NFLOG, ULOG_MAXNLGROUPS, NULL,
423-
THIS_MODULE);
423+
NULL, THIS_MODULE);
424424
if (!nflognl)
425425
return -ENOMEM;
426426

net/ipv6/netfilter/ip6_queue.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ static int __init ip6_queue_init(void)
657657
struct proc_dir_entry *proc;
658658

659659
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,
661661
THIS_MODULE);
662662
if (ipqnl == NULL) {
663663
printk(KERN_ERR "ip6_queue: failed to create netlink socket\n");

net/netfilter/nfnetlink.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ static int __init nfnetlink_init(void)
265265
printk("Netfilter messages via NETLINK v%s.\n", nfversion);
266266

267267
nfnl = netlink_kernel_create(NETLINK_NETFILTER, NFNLGRP_MAX,
268-
nfnetlink_rcv, THIS_MODULE);
268+
nfnetlink_rcv, NULL, THIS_MODULE);
269269
if (!nfnl) {
270270
printk(KERN_ERR "cannot initialize nfnetlink!\n");
271271
return -1;

net/netlink/af_netlink.c

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
#include <linux/types.h>
5757
#include <linux/audit.h>
5858
#include <linux/selinux.h>
59+
#include <linux/mutex.h>
5960

6061
#include <net/sock.h>
6162
#include <net/scm.h>
@@ -76,7 +77,8 @@ struct netlink_sock {
7677
unsigned long state;
7778
wait_queue_head_t wait;
7879
struct netlink_callback *cb;
79-
spinlock_t cb_lock;
80+
struct mutex *cb_mutex;
81+
struct mutex cb_def_mutex;
8082
void (*data_ready)(struct sock *sk, int bytes);
8183
struct module *module;
8284
};
@@ -108,6 +110,7 @@ struct netlink_table {
108110
unsigned long *listeners;
109111
unsigned int nl_nonroot;
110112
unsigned int groups;
113+
struct mutex *cb_mutex;
111114
struct module *module;
112115
int registered;
113116
};
@@ -370,7 +373,8 @@ static struct proto netlink_proto = {
370373
.obj_size = sizeof(struct netlink_sock),
371374
};
372375

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)
374378
{
375379
struct sock *sk;
376380
struct netlink_sock *nlk;
@@ -384,7 +388,8 @@ static int __netlink_create(struct socket *sock, int protocol)
384388
sock_init_data(sock, sk);
385389

386390
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);
388393
init_waitqueue_head(&nlk->wait);
389394

390395
sk->sk_destruct = netlink_sock_destruct;
@@ -395,6 +400,7 @@ static int __netlink_create(struct socket *sock, int protocol)
395400
static int netlink_create(struct socket *sock, int protocol)
396401
{
397402
struct module *module = NULL;
403+
struct mutex *cb_mutex;
398404
struct netlink_sock *nlk;
399405
int err = 0;
400406

@@ -417,9 +423,10 @@ static int netlink_create(struct socket *sock, int protocol)
417423
if (nl_table[protocol].registered &&
418424
try_module_get(nl_table[protocol].module))
419425
module = nl_table[protocol].module;
426+
cb_mutex = nl_table[protocol].cb_mutex;
420427
netlink_unlock_table();
421428

422-
if ((err = __netlink_create(sock, protocol)) < 0)
429+
if ((err = __netlink_create(sock, cb_mutex, protocol)) < 0)
423430
goto out_module;
424431

425432
nlk = nlk_sk(sock->sk);
@@ -444,14 +451,14 @@ static int netlink_release(struct socket *sock)
444451
sock_orphan(sk);
445452
nlk = nlk_sk(sk);
446453

447-
spin_lock(&nlk->cb_lock);
454+
mutex_lock(nlk->cb_mutex);
448455
if (nlk->cb) {
449456
if (nlk->cb->done)
450457
nlk->cb->done(nlk->cb);
451458
netlink_destroy_callback(nlk->cb);
452459
nlk->cb = NULL;
453460
}
454-
spin_unlock(&nlk->cb_lock);
461+
mutex_unlock(nlk->cb_mutex);
455462

456463
/* OK. Socket is unlinked, and, therefore,
457464
no new packets will arrive */
@@ -1266,7 +1273,7 @@ static void netlink_data_ready(struct sock *sk, int len)
12661273
struct sock *
12671274
netlink_kernel_create(int unit, unsigned int groups,
12681275
void (*input)(struct sock *sk, int len),
1269-
struct module *module)
1276+
struct mutex *cb_mutex, struct module *module)
12701277
{
12711278
struct socket *sock;
12721279
struct sock *sk;
@@ -1281,7 +1288,7 @@ netlink_kernel_create(int unit, unsigned int groups,
12811288
if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock))
12821289
return NULL;
12831290

1284-
if (__netlink_create(sock, unit) < 0)
1291+
if (__netlink_create(sock, cb_mutex, unit) < 0)
12851292
goto out_sock_release;
12861293

12871294
if (groups < 32)
@@ -1305,6 +1312,7 @@ netlink_kernel_create(int unit, unsigned int groups,
13051312
netlink_table_grab();
13061313
nl_table[unit].groups = groups;
13071314
nl_table[unit].listeners = listeners;
1315+
nl_table[unit].cb_mutex = cb_mutex;
13081316
nl_table[unit].module = module;
13091317
nl_table[unit].registered = 1;
13101318
netlink_table_ungrab();
@@ -1347,7 +1355,7 @@ static int netlink_dump(struct sock *sk)
13471355
if (!skb)
13481356
goto errout;
13491357

1350-
spin_lock(&nlk->cb_lock);
1358+
mutex_lock(nlk->cb_mutex);
13511359

13521360
cb = nlk->cb;
13531361
if (cb == NULL) {
@@ -1358,7 +1366,7 @@ static int netlink_dump(struct sock *sk)
13581366
len = cb->dump(skb, cb);
13591367

13601368
if (len > 0) {
1361-
spin_unlock(&nlk->cb_lock);
1369+
mutex_unlock(nlk->cb_mutex);
13621370
skb_queue_tail(&sk->sk_receive_queue, skb);
13631371
sk->sk_data_ready(sk, len);
13641372
return 0;
@@ -1376,13 +1384,13 @@ static int netlink_dump(struct sock *sk)
13761384
if (cb->done)
13771385
cb->done(cb);
13781386
nlk->cb = NULL;
1379-
spin_unlock(&nlk->cb_lock);
1387+
mutex_unlock(nlk->cb_mutex);
13801388

13811389
netlink_destroy_callback(cb);
13821390
return 0;
13831391

13841392
errout_skb:
1385-
spin_unlock(&nlk->cb_lock);
1393+
mutex_unlock(nlk->cb_mutex);
13861394
kfree_skb(skb);
13871395
errout:
13881396
return err;
@@ -1414,15 +1422,15 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
14141422
}
14151423
nlk = nlk_sk(sk);
14161424
/* A dump or destruction is in progress... */
1417-
spin_lock(&nlk->cb_lock);
1425+
mutex_lock(nlk->cb_mutex);
14181426
if (nlk->cb || sock_flag(sk, SOCK_DEAD)) {
1419-
spin_unlock(&nlk->cb_lock);
1427+
mutex_unlock(nlk->cb_mutex);
14201428
netlink_destroy_callback(cb);
14211429
sock_put(sk);
14221430
return -EBUSY;
14231431
}
14241432
nlk->cb = cb;
1425-
spin_unlock(&nlk->cb_lock);
1433+
mutex_unlock(nlk->cb_mutex);
14261434

14271435
netlink_dump(sk);
14281436
sock_put(sk);

net/netlink/genetlink.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ static int __init genl_init(void)
558558

559559
netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV);
560560
genl_sock = netlink_kernel_create(NETLINK_GENERIC, GENL_MAX_ID,
561-
genl_rcv, THIS_MODULE);
561+
genl_rcv, NULL, THIS_MODULE);
562562
if (genl_sock == NULL)
563563
panic("GENL: Cannot initialize generic netlink\n");
564564

net/xfrm/xfrm_user.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2444,7 +2444,7 @@ static int __init xfrm_user_init(void)
24442444
printk(KERN_INFO "Initializing XFRM netlink socket\n");
24452445

24462446
nlsk = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX,
2447-
xfrm_netlink_rcv, THIS_MODULE);
2447+
xfrm_netlink_rcv, NULL, THIS_MODULE);
24482448
if (nlsk == NULL)
24492449
return -ENOMEM;
24502450
rcu_assign_pointer(xfrm_nl, nlsk);

security/selinux/netlink.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ void selnl_notify_policyload(u32 seqno)
104104

105105
static int __init selnl_init(void)
106106
{
107-
selnl = netlink_kernel_create(NETLINK_SELINUX, SELNLGRP_MAX, NULL,
107+
selnl = netlink_kernel_create(NETLINK_SELINUX, SELNLGRP_MAX, NULL, NULL,
108108
THIS_MODULE);
109109
if (selnl == NULL)
110110
panic("SELinux: Cannot create netlink socket.");

0 commit comments

Comments
 (0)