aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2005-08-14 22:31:36 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 19:00:58 -0400
commitab33a1711cf60bfb562b1ab89ac9f23d1425e8b1 (patch)
treeabd497f5b7023ff748001d6ef182d74f882f1a07
parentac6d439d2097b72ea0cbc2322ce1263a38bc1fd0 (diff)
[NETLINK]: Return -EPROTONOSUPPORT in netlink_create() if no kernel socket is registered
This is necessary for dynamic number of netlink groups to make sure we know the number of possible groups before bind() is called. With this change pure userspace communication using unused netlink protocols becomes impossible. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/netlink/af_netlink.c72
1 files changed, 44 insertions, 28 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 3c56b96b4a4b..444ed223ee43 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -102,6 +102,7 @@ struct netlink_table {
102 struct hlist_head mc_list; 102 struct hlist_head mc_list;
103 unsigned int nl_nonroot; 103 unsigned int nl_nonroot;
104 struct module *module; 104 struct module *module;
105 int registered;
105}; 106};
106 107
107static struct netlink_table *nl_table; 108static struct netlink_table *nl_table;
@@ -343,11 +344,32 @@ static struct proto netlink_proto = {
343 .obj_size = sizeof(struct netlink_sock), 344 .obj_size = sizeof(struct netlink_sock),
344}; 345};
345 346
346static int netlink_create(struct socket *sock, int protocol) 347static int __netlink_create(struct socket *sock, int protocol)
347{ 348{
348 struct sock *sk; 349 struct sock *sk;
349 struct netlink_sock *nlk; 350 struct netlink_sock *nlk;
350 struct module *module; 351
352 sock->ops = &netlink_ops;
353
354 sk = sk_alloc(PF_NETLINK, GFP_KERNEL, &netlink_proto, 1);
355 if (!sk)
356 return -ENOMEM;
357
358 sock_init_data(sock, sk);
359
360 nlk = nlk_sk(sk);
361 spin_lock_init(&nlk->cb_lock);
362 init_waitqueue_head(&nlk->wait);
363
364 sk->sk_destruct = netlink_sock_destruct;
365 sk->sk_protocol = protocol;
366 return 0;
367}
368
369static int netlink_create(struct socket *sock, int protocol)
370{
371 struct module *module = NULL;
372 int err = 0;
351 373
352 sock->state = SS_UNCONNECTED; 374 sock->state = SS_UNCONNECTED;
353 375
@@ -358,41 +380,33 @@ static int netlink_create(struct socket *sock, int protocol)
358 return -EPROTONOSUPPORT; 380 return -EPROTONOSUPPORT;
359 381
360 netlink_lock_table(); 382 netlink_lock_table();
361 if (!nl_table[protocol].hash.entries) {
362#ifdef CONFIG_KMOD 383#ifdef CONFIG_KMOD
363 /* We do 'best effort'. If we find a matching module, 384 if (!nl_table[protocol].registered) {
364 * it is loaded. If not, we don't return an error to
365 * allow pure userspace<->userspace communication. -HW
366 */
367 netlink_unlock_table(); 385 netlink_unlock_table();
368 request_module("net-pf-%d-proto-%d", PF_NETLINK, protocol); 386 request_module("net-pf-%d-proto-%d", PF_NETLINK, protocol);
369 netlink_lock_table(); 387 netlink_lock_table();
370#endif
371 } 388 }
372 module = nl_table[protocol].module; 389#endif
373 if (!try_module_get(module)) 390 if (nl_table[protocol].registered &&
374 module = NULL; 391 try_module_get(nl_table[protocol].module))
392 module = nl_table[protocol].module;
393 else
394 err = -EPROTONOSUPPORT;
375 netlink_unlock_table(); 395 netlink_unlock_table();
376 396
377 sock->ops = &netlink_ops; 397 if (err)
378 398 goto out;
379 sk = sk_alloc(PF_NETLINK, GFP_KERNEL, &netlink_proto, 1);
380 if (!sk) {
381 module_put(module);
382 return -ENOMEM;
383 }
384
385 sock_init_data(sock, sk);
386 399
387 nlk = nlk_sk(sk); 400 if ((err = __netlink_create(sock, protocol) < 0))
401 goto out_module;
388 402
389 nlk->module = module; 403 nlk_sk(sock->sk)->module = module;
390 spin_lock_init(&nlk->cb_lock); 404out:
391 init_waitqueue_head(&nlk->wait); 405 return err;
392 sk->sk_destruct = netlink_sock_destruct;
393 406
394 sk->sk_protocol = protocol; 407out_module:
395 return 0; 408 module_put(module);
409 goto out;
396} 410}
397 411
398static int netlink_release(struct socket *sock) 412static int netlink_release(struct socket *sock)
@@ -437,6 +451,7 @@ static int netlink_release(struct socket *sock)
437 if (nlk->flags & NETLINK_KERNEL_SOCKET) { 451 if (nlk->flags & NETLINK_KERNEL_SOCKET) {
438 netlink_table_grab(); 452 netlink_table_grab();
439 nl_table[sk->sk_protocol].module = NULL; 453 nl_table[sk->sk_protocol].module = NULL;
454 nl_table[sk->sk_protocol].registered = 0;
440 netlink_table_ungrab(); 455 netlink_table_ungrab();
441 } 456 }
442 457
@@ -1082,7 +1097,7 @@ netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len), struct
1082 if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock)) 1097 if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock))
1083 return NULL; 1098 return NULL;
1084 1099
1085 if (netlink_create(sock, unit) < 0) 1100 if (__netlink_create(sock, unit) < 0)
1086 goto out_sock_release; 1101 goto out_sock_release;
1087 1102
1088 sk = sock->sk; 1103 sk = sock->sk;
@@ -1098,6 +1113,7 @@ netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len), struct
1098 1113
1099 netlink_table_grab(); 1114 netlink_table_grab();
1100 nl_table[unit].module = module; 1115 nl_table[unit].module = module;
1116 nl_table[unit].registered = 1;
1101 netlink_table_ungrab(); 1117 netlink_table_ungrab();
1102 1118
1103 return sk; 1119 return sk;