aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2005-08-14 22:27:13 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 19:00:45 -0400
commit77247bbb3094246be9d057e7be442cc708f123a8 (patch)
treef6129e1aa25be790fdf38d5f39e1d38b2fa19587
parentdb080529798b497eb5a37b92a25e966be5a7dd5d (diff)
[NETLINK]: Fix module refcounting problems
Use-after-free: the struct proto_ops containing the module pointer is freed when a socket with pid=0 is released, which besides for kernel sockets is true for all unbound sockets. Module refcount leak: when the kernel socket is closed before all user sockets have been closed the proto_ops struct for this family is replaced by the generic one and the module refcount can't be dropped. The second problem can't be solved cleanly using module refcounting in the generic socket code, so this patch adds explicit refcounting to netlink_create/netlink_release. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/netlink/af_netlink.c100
1 files changed, 35 insertions, 65 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 7b7b45a19597..c41a88100fea 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -73,8 +73,12 @@ struct netlink_sock {
73 struct netlink_callback *cb; 73 struct netlink_callback *cb;
74 spinlock_t cb_lock; 74 spinlock_t cb_lock;
75 void (*data_ready)(struct sock *sk, int bytes); 75 void (*data_ready)(struct sock *sk, int bytes);
76 struct module *module;
77 u32 flags;
76}; 78};
77 79
80#define NETLINK_KERNEL_SOCKET 0x1
81
78static inline struct netlink_sock *nlk_sk(struct sock *sk) 82static inline struct netlink_sock *nlk_sk(struct sock *sk)
79{ 83{
80 return (struct netlink_sock *)sk; 84 return (struct netlink_sock *)sk;
@@ -97,7 +101,7 @@ struct netlink_table {
97 struct nl_pid_hash hash; 101 struct nl_pid_hash hash;
98 struct hlist_head mc_list; 102 struct hlist_head mc_list;
99 unsigned int nl_nonroot; 103 unsigned int nl_nonroot;
100 struct proto_ops *p_ops; 104 struct module *module;
101}; 105};
102 106
103static struct netlink_table *nl_table; 107static struct netlink_table *nl_table;
@@ -338,6 +342,7 @@ static int netlink_create(struct socket *sock, int protocol)
338{ 342{
339 struct sock *sk; 343 struct sock *sk;
340 struct netlink_sock *nlk; 344 struct netlink_sock *nlk;
345 struct module *module;
341 346
342 sock->state = SS_UNCONNECTED; 347 sock->state = SS_UNCONNECTED;
343 348
@@ -347,30 +352,36 @@ static int netlink_create(struct socket *sock, int protocol)
347 if (protocol<0 || protocol >= MAX_LINKS) 352 if (protocol<0 || protocol >= MAX_LINKS)
348 return -EPROTONOSUPPORT; 353 return -EPROTONOSUPPORT;
349 354
350 netlink_table_grab(); 355 netlink_lock_table();
351 if (!nl_table[protocol].hash.entries) { 356 if (!nl_table[protocol].hash.entries) {
352#ifdef CONFIG_KMOD 357#ifdef CONFIG_KMOD
353 /* We do 'best effort'. If we find a matching module, 358 /* We do 'best effort'. If we find a matching module,
354 * it is loaded. If not, we don't return an error to 359 * it is loaded. If not, we don't return an error to
355 * allow pure userspace<->userspace communication. -HW 360 * allow pure userspace<->userspace communication. -HW
356 */ 361 */
357 netlink_table_ungrab(); 362 netlink_unlock_table();
358 request_module("net-pf-%d-proto-%d", PF_NETLINK, protocol); 363 request_module("net-pf-%d-proto-%d", PF_NETLINK, protocol);
359 netlink_table_grab(); 364 netlink_lock_table();
360#endif 365#endif
361 } 366 }
362 netlink_table_ungrab(); 367 module = nl_table[protocol].module;
368 if (!try_module_get(module))
369 module = NULL;
370 netlink_unlock_table();
363 371
364 sock->ops = nl_table[protocol].p_ops; 372 sock->ops = &netlink_ops;
365 373
366 sk = sk_alloc(PF_NETLINK, GFP_KERNEL, &netlink_proto, 1); 374 sk = sk_alloc(PF_NETLINK, GFP_KERNEL, &netlink_proto, 1);
367 if (!sk) 375 if (!sk) {
376 module_put(module);
368 return -ENOMEM; 377 return -ENOMEM;
378 }
369 379
370 sock_init_data(sock, sk); 380 sock_init_data(sock, sk);
371 381
372 nlk = nlk_sk(sk); 382 nlk = nlk_sk(sk);
373 383
384 nlk->module = module;
374 spin_lock_init(&nlk->cb_lock); 385 spin_lock_init(&nlk->cb_lock);
375 init_waitqueue_head(&nlk->wait); 386 init_waitqueue_head(&nlk->wait);
376 sk->sk_destruct = netlink_sock_destruct; 387 sk->sk_destruct = netlink_sock_destruct;
@@ -415,22 +426,15 @@ static int netlink_release(struct socket *sock)
415 notifier_call_chain(&netlink_chain, NETLINK_URELEASE, &n); 426 notifier_call_chain(&netlink_chain, NETLINK_URELEASE, &n);
416 } 427 }
417 428
418 /* When this is a kernel socket, we need to remove the owner pointer, 429 if (nlk->module)
419 * since we don't know whether the module will be dying at any given 430 module_put(nlk->module);
420 * point - HW
421 */
422 if (!nlk->pid) {
423 struct proto_ops *p_tmp;
424 431
432 if (nlk->flags & NETLINK_KERNEL_SOCKET) {
425 netlink_table_grab(); 433 netlink_table_grab();
426 p_tmp = nl_table[sk->sk_protocol].p_ops; 434 nl_table[sk->sk_protocol].module = NULL;
427 if (p_tmp != &netlink_ops) {
428 nl_table[sk->sk_protocol].p_ops = &netlink_ops;
429 kfree(p_tmp);
430 }
431 netlink_table_ungrab(); 435 netlink_table_ungrab();
432 } 436 }
433 437
434 sock_put(sk); 438 sock_put(sk);
435 return 0; 439 return 0;
436} 440}
@@ -1060,9 +1064,9 @@ static void netlink_data_ready(struct sock *sk, int len)
1060struct sock * 1064struct sock *
1061netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len), struct module *module) 1065netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len), struct module *module)
1062{ 1066{
1063 struct proto_ops *p_ops;
1064 struct socket *sock; 1067 struct socket *sock;
1065 struct sock *sk; 1068 struct sock *sk;
1069 struct netlink_sock *nlk;
1066 1070
1067 if (!nl_table) 1071 if (!nl_table)
1068 return NULL; 1072 return NULL;
@@ -1070,64 +1074,32 @@ netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len), struct
1070 if (unit<0 || unit>=MAX_LINKS) 1074 if (unit<0 || unit>=MAX_LINKS)
1071 return NULL; 1075 return NULL;
1072 1076
1073 /* Do a quick check, to make us not go down to netlink_insert()
1074 * if protocol already has kernel socket.
1075 */
1076 sk = netlink_lookup(unit, 0);
1077 if (unlikely(sk)) {
1078 sock_put(sk);
1079 return NULL;
1080 }
1081
1082 if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock)) 1077 if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock))
1083 return NULL; 1078 return NULL;
1084 1079
1085 sk = NULL; 1080 if (netlink_create(sock, unit) < 0)
1086 if (module) { 1081 goto out_sock_release;
1087 /* Every registering protocol implemented in a module needs
1088 * it's own p_ops, since the socket code cannot deal with
1089 * module refcounting otherwise. -HW
1090 */
1091 p_ops = kmalloc(sizeof(*p_ops), GFP_KERNEL);
1092 if (!p_ops)
1093 goto out_sock_release;
1094
1095 memcpy(p_ops, &netlink_ops, sizeof(*p_ops));
1096 p_ops->owner = module;
1097 } else
1098 p_ops = &netlink_ops;
1099
1100 netlink_table_grab();
1101 nl_table[unit].p_ops = p_ops;
1102 netlink_table_ungrab();
1103
1104 if (netlink_create(sock, unit) < 0) {
1105 sk = NULL;
1106 goto out_kfree_p_ops;
1107 }
1108 1082
1109 sk = sock->sk; 1083 sk = sock->sk;
1110 sk->sk_data_ready = netlink_data_ready; 1084 sk->sk_data_ready = netlink_data_ready;
1111 if (input) 1085 if (input)
1112 nlk_sk(sk)->data_ready = input; 1086 nlk_sk(sk)->data_ready = input;
1113 1087
1114 if (netlink_insert(sk, 0)) { 1088 if (netlink_insert(sk, 0))
1115 sk = NULL; 1089 goto out_sock_release;
1116 goto out_kfree_p_ops;
1117 }
1118 1090
1119 return sk; 1091 nlk = nlk_sk(sk);
1092 nlk->flags |= NETLINK_KERNEL_SOCKET;
1120 1093
1121out_kfree_p_ops:
1122 netlink_table_grab(); 1094 netlink_table_grab();
1123 if (nl_table[unit].p_ops != &netlink_ops) { 1095 nl_table[unit].module = module;
1124 kfree(nl_table[unit].p_ops);
1125 nl_table[unit].p_ops = &netlink_ops;
1126 }
1127 netlink_table_ungrab(); 1096 netlink_table_ungrab();
1097
1098 return sk;
1099
1128out_sock_release: 1100out_sock_release:
1129 sock_release(sock); 1101 sock_release(sock);
1130 return sk; 1102 return NULL;
1131} 1103}
1132 1104
1133void netlink_set_nonroot(int protocol, unsigned int flags) 1105void netlink_set_nonroot(int protocol, unsigned int flags)
@@ -1490,8 +1462,6 @@ enomem:
1490 for (i = 0; i < MAX_LINKS; i++) { 1462 for (i = 0; i < MAX_LINKS; i++) {
1491 struct nl_pid_hash *hash = &nl_table[i].hash; 1463 struct nl_pid_hash *hash = &nl_table[i].hash;
1492 1464
1493 nl_table[i].p_ops = &netlink_ops;
1494
1495 hash->table = nl_pid_hash_alloc(1 * sizeof(*hash->table)); 1465 hash->table = nl_pid_hash_alloc(1 * sizeof(*hash->table));
1496 if (!hash->table) { 1466 if (!hash->table) {
1497 while (i-- > 0) 1467 while (i-- > 0)