Commit ab33a1711cf60bfb562b1ab89ac9f23d1425e8b1

Authored by Patrick McHardy
Committed by David S. Miller
1 parent ac6d439d20

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

Showing 1 changed file with 44 additions and 28 deletions Side-by-side Diff

net/netlink/af_netlink.c
... ... @@ -102,6 +102,7 @@
102 102 struct hlist_head mc_list;
103 103 unsigned int nl_nonroot;
104 104 struct module *module;
  105 + int registered;
105 106 };
106 107  
107 108 static struct netlink_table *nl_table;
108 109  
109 110  
... ... @@ -343,12 +344,33 @@
343 344 .obj_size = sizeof(struct netlink_sock),
344 345 };
345 346  
346   -static int netlink_create(struct socket *sock, int protocol)
  347 +static int __netlink_create(struct socket *sock, int protocol)
347 348 {
348 349 struct sock *sk;
349 350 struct netlink_sock *nlk;
350   - struct module *module;
351 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 +
  369 +static int netlink_create(struct socket *sock, int protocol)
  370 +{
  371 + struct module *module = NULL;
  372 + int err = 0;
  373 +
352 374 sock->state = SS_UNCONNECTED;
353 375  
354 376 if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
355 377  
356 378  
357 379  
358 380  
359 381  
360 382  
361 383  
... ... @@ -358,41 +380,33 @@
358 380 return -EPROTONOSUPPORT;
359 381  
360 382 netlink_lock_table();
361   - if (!nl_table[protocol].hash.entries) {
362 383 #ifdef CONFIG_KMOD
363   - /* We do 'best effort'. If we find a matching module,
364   - * it is loaded. If not, we don't return an error to
365   - * allow pure userspace<->userspace communication. -HW
366   - */
  384 + if (!nl_table[protocol].registered) {
367 385 netlink_unlock_table();
368 386 request_module("net-pf-%d-proto-%d", PF_NETLINK, protocol);
369 387 netlink_lock_table();
370   -#endif
371 388 }
372   - module = nl_table[protocol].module;
373   - if (!try_module_get(module))
374   - module = NULL;
  389 +#endif
  390 + if (nl_table[protocol].registered &&
  391 + try_module_get(nl_table[protocol].module))
  392 + module = nl_table[protocol].module;
  393 + else
  394 + err = -EPROTONOSUPPORT;
375 395 netlink_unlock_table();
376 396  
377   - sock->ops = &netlink_ops;
  397 + if (err)
  398 + goto out;
378 399  
379   - sk = sk_alloc(PF_NETLINK, GFP_KERNEL, &netlink_proto, 1);
380   - if (!sk) {
381   - module_put(module);
382   - return -ENOMEM;
383   - }
  400 + if ((err = __netlink_create(sock, protocol) < 0))
  401 + goto out_module;
384 402  
385   - sock_init_data(sock, sk);
  403 + nlk_sk(sock->sk)->module = module;
  404 +out:
  405 + return err;
386 406  
387   - nlk = nlk_sk(sk);
388   -
389   - nlk->module = module;
390   - spin_lock_init(&nlk->cb_lock);
391   - init_waitqueue_head(&nlk->wait);
392   - sk->sk_destruct = netlink_sock_destruct;
393   -
394   - sk->sk_protocol = protocol;
395   - return 0;
  407 +out_module:
  408 + module_put(module);
  409 + goto out;
396 410 }
397 411  
398 412 static int netlink_release(struct socket *sock)
... ... @@ -437,6 +451,7 @@
437 451 if (nlk->flags & NETLINK_KERNEL_SOCKET) {
438 452 netlink_table_grab();
439 453 nl_table[sk->sk_protocol].module = NULL;
  454 + nl_table[sk->sk_protocol].registered = 0;
440 455 netlink_table_ungrab();
441 456 }
442 457  
... ... @@ -1082,7 +1097,7 @@
1082 1097 if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock))
1083 1098 return NULL;
1084 1099  
1085   - if (netlink_create(sock, unit) < 0)
  1100 + if (__netlink_create(sock, unit) < 0)
1086 1101 goto out_sock_release;
1087 1102  
1088 1103 sk = sock->sk;
... ... @@ -1098,6 +1113,7 @@
1098 1113  
1099 1114 netlink_table_grab();
1100 1115 nl_table[unit].module = module;
  1116 + nl_table[unit].registered = 1;
1101 1117 netlink_table_ungrab();
1102 1118  
1103 1119 return sk;