diff options
Diffstat (limited to 'net/netlink')
-rw-r--r-- | net/netlink/af_netlink.c | 83 |
1 files changed, 41 insertions, 42 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 61fd2773a453..46f3e44bb83a 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -227,7 +227,7 @@ static inline struct sock *netlink_lookup(struct net *net, int protocol, | |||
227 | read_lock(&nl_table_lock); | 227 | read_lock(&nl_table_lock); |
228 | head = nl_pid_hashfn(hash, pid); | 228 | head = nl_pid_hashfn(hash, pid); |
229 | sk_for_each(sk, node, head) { | 229 | sk_for_each(sk, node, head) { |
230 | if ((sk->sk_net == net) && (nlk_sk(sk)->pid == pid)) { | 230 | if (net_eq(sock_net(sk), net) && (nlk_sk(sk)->pid == pid)) { |
231 | sock_hold(sk); | 231 | sock_hold(sk); |
232 | goto found; | 232 | goto found; |
233 | } | 233 | } |
@@ -347,7 +347,7 @@ static int netlink_insert(struct sock *sk, struct net *net, u32 pid) | |||
347 | head = nl_pid_hashfn(hash, pid); | 347 | head = nl_pid_hashfn(hash, pid); |
348 | len = 0; | 348 | len = 0; |
349 | sk_for_each(osk, node, head) { | 349 | sk_for_each(osk, node, head) { |
350 | if ((osk->sk_net == net) && (nlk_sk(osk)->pid == pid)) | 350 | if (net_eq(sock_net(osk), net) && (nlk_sk(osk)->pid == pid)) |
351 | break; | 351 | break; |
352 | len++; | 352 | len++; |
353 | } | 353 | } |
@@ -485,7 +485,7 @@ static int netlink_release(struct socket *sock) | |||
485 | 485 | ||
486 | if (nlk->pid && !nlk->subscriptions) { | 486 | if (nlk->pid && !nlk->subscriptions) { |
487 | struct netlink_notify n = { | 487 | struct netlink_notify n = { |
488 | .net = sk->sk_net, | 488 | .net = sock_net(sk), |
489 | .protocol = sk->sk_protocol, | 489 | .protocol = sk->sk_protocol, |
490 | .pid = nlk->pid, | 490 | .pid = nlk->pid, |
491 | }; | 491 | }; |
@@ -517,7 +517,7 @@ static int netlink_release(struct socket *sock) | |||
517 | static int netlink_autobind(struct socket *sock) | 517 | static int netlink_autobind(struct socket *sock) |
518 | { | 518 | { |
519 | struct sock *sk = sock->sk; | 519 | struct sock *sk = sock->sk; |
520 | struct net *net = sk->sk_net; | 520 | struct net *net = sock_net(sk); |
521 | struct nl_pid_hash *hash = &nl_table[sk->sk_protocol].hash; | 521 | struct nl_pid_hash *hash = &nl_table[sk->sk_protocol].hash; |
522 | struct hlist_head *head; | 522 | struct hlist_head *head; |
523 | struct sock *osk; | 523 | struct sock *osk; |
@@ -531,7 +531,7 @@ retry: | |||
531 | netlink_table_grab(); | 531 | netlink_table_grab(); |
532 | head = nl_pid_hashfn(hash, pid); | 532 | head = nl_pid_hashfn(hash, pid); |
533 | sk_for_each(osk, node, head) { | 533 | sk_for_each(osk, node, head) { |
534 | if ((osk->sk_net != net)) | 534 | if (!net_eq(sock_net(osk), net)) |
535 | continue; | 535 | continue; |
536 | if (nlk_sk(osk)->pid == pid) { | 536 | if (nlk_sk(osk)->pid == pid) { |
537 | /* Bind collision, search negative pid values. */ | 537 | /* Bind collision, search negative pid values. */ |
@@ -610,7 +610,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, | |||
610 | int addr_len) | 610 | int addr_len) |
611 | { | 611 | { |
612 | struct sock *sk = sock->sk; | 612 | struct sock *sk = sock->sk; |
613 | struct net *net = sk->sk_net; | 613 | struct net *net = sock_net(sk); |
614 | struct netlink_sock *nlk = nlk_sk(sk); | 614 | struct netlink_sock *nlk = nlk_sk(sk); |
615 | struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; | 615 | struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; |
616 | int err; | 616 | int err; |
@@ -719,7 +719,7 @@ static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid) | |||
719 | struct sock *sock; | 719 | struct sock *sock; |
720 | struct netlink_sock *nlk; | 720 | struct netlink_sock *nlk; |
721 | 721 | ||
722 | sock = netlink_lookup(ssk->sk_net, ssk->sk_protocol, pid); | 722 | sock = netlink_lookup(sock_net(ssk), ssk->sk_protocol, pid); |
723 | if (!sock) | 723 | if (!sock) |
724 | return ERR_PTR(-ECONNREFUSED); | 724 | return ERR_PTR(-ECONNREFUSED); |
725 | 725 | ||
@@ -885,6 +885,13 @@ retry: | |||
885 | if (netlink_is_kernel(sk)) | 885 | if (netlink_is_kernel(sk)) |
886 | return netlink_unicast_kernel(sk, skb); | 886 | return netlink_unicast_kernel(sk, skb); |
887 | 887 | ||
888 | if (sk_filter(sk, skb)) { | ||
889 | int err = skb->len; | ||
890 | kfree_skb(skb); | ||
891 | sock_put(sk); | ||
892 | return err; | ||
893 | } | ||
894 | |||
888 | err = netlink_attachskb(sk, skb, nonblock, &timeo, ssk); | 895 | err = netlink_attachskb(sk, skb, nonblock, &timeo, ssk); |
889 | if (err == 1) | 896 | if (err == 1) |
890 | goto retry; | 897 | goto retry; |
@@ -954,7 +961,7 @@ static inline int do_one_broadcast(struct sock *sk, | |||
954 | !test_bit(p->group - 1, nlk->groups)) | 961 | !test_bit(p->group - 1, nlk->groups)) |
955 | goto out; | 962 | goto out; |
956 | 963 | ||
957 | if ((sk->sk_net != p->net)) | 964 | if (!net_eq(sock_net(sk), p->net)) |
958 | goto out; | 965 | goto out; |
959 | 966 | ||
960 | if (p->failure) { | 967 | if (p->failure) { |
@@ -979,6 +986,9 @@ static inline int do_one_broadcast(struct sock *sk, | |||
979 | netlink_overrun(sk); | 986 | netlink_overrun(sk); |
980 | /* Clone failed. Notify ALL listeners. */ | 987 | /* Clone failed. Notify ALL listeners. */ |
981 | p->failure = 1; | 988 | p->failure = 1; |
989 | } else if (sk_filter(sk, p->skb2)) { | ||
990 | kfree_skb(p->skb2); | ||
991 | p->skb2 = NULL; | ||
982 | } else if ((val = netlink_broadcast_deliver(sk, p->skb2)) < 0) { | 992 | } else if ((val = netlink_broadcast_deliver(sk, p->skb2)) < 0) { |
983 | netlink_overrun(sk); | 993 | netlink_overrun(sk); |
984 | } else { | 994 | } else { |
@@ -995,7 +1005,7 @@ out: | |||
995 | int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, | 1005 | int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, |
996 | u32 group, gfp_t allocation) | 1006 | u32 group, gfp_t allocation) |
997 | { | 1007 | { |
998 | struct net *net = ssk->sk_net; | 1008 | struct net *net = sock_net(ssk); |
999 | struct netlink_broadcast_data info; | 1009 | struct netlink_broadcast_data info; |
1000 | struct hlist_node *node; | 1010 | struct hlist_node *node; |
1001 | struct sock *sk; | 1011 | struct sock *sk; |
@@ -1053,7 +1063,7 @@ static inline int do_one_set_err(struct sock *sk, | |||
1053 | if (sk == p->exclude_sk) | 1063 | if (sk == p->exclude_sk) |
1054 | goto out; | 1064 | goto out; |
1055 | 1065 | ||
1056 | if (sk->sk_net != p->exclude_sk->sk_net) | 1066 | if (sock_net(sk) != sock_net(p->exclude_sk)) |
1057 | goto out; | 1067 | goto out; |
1058 | 1068 | ||
1059 | if (nlk->pid == p->pid || p->group - 1 >= nlk->ngroups || | 1069 | if (nlk->pid == p->pid || p->group - 1 >= nlk->ngroups || |
@@ -1343,22 +1353,6 @@ static void netlink_data_ready(struct sock *sk, int len) | |||
1343 | * queueing. | 1353 | * queueing. |
1344 | */ | 1354 | */ |
1345 | 1355 | ||
1346 | static void __netlink_release(struct sock *sk) | ||
1347 | { | ||
1348 | /* | ||
1349 | * Last sock_put should drop referrence to sk->sk_net. It has already | ||
1350 | * been dropped in netlink_kernel_create. Taking referrence to stopping | ||
1351 | * namespace is not an option. | ||
1352 | * Take referrence to a socket to remove it from netlink lookup table | ||
1353 | * _alive_ and after that destroy it in the context of init_net. | ||
1354 | */ | ||
1355 | |||
1356 | sock_hold(sk); | ||
1357 | sock_release(sk->sk_socket); | ||
1358 | sk->sk_net = get_net(&init_net); | ||
1359 | sock_put(sk); | ||
1360 | } | ||
1361 | |||
1362 | struct sock * | 1356 | struct sock * |
1363 | netlink_kernel_create(struct net *net, int unit, unsigned int groups, | 1357 | netlink_kernel_create(struct net *net, int unit, unsigned int groups, |
1364 | void (*input)(struct sk_buff *skb), | 1358 | void (*input)(struct sk_buff *skb), |
@@ -1387,8 +1381,7 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups, | |||
1387 | goto out_sock_release_nosk; | 1381 | goto out_sock_release_nosk; |
1388 | 1382 | ||
1389 | sk = sock->sk; | 1383 | sk = sock->sk; |
1390 | put_net(sk->sk_net); | 1384 | sk_change_net(sk, net); |
1391 | sk->sk_net = net; | ||
1392 | 1385 | ||
1393 | if (groups < 32) | 1386 | if (groups < 32) |
1394 | groups = 32; | 1387 | groups = 32; |
@@ -1423,7 +1416,7 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups, | |||
1423 | 1416 | ||
1424 | out_sock_release: | 1417 | out_sock_release: |
1425 | kfree(listeners); | 1418 | kfree(listeners); |
1426 | __netlink_release(sk); | 1419 | netlink_kernel_release(sk); |
1427 | return NULL; | 1420 | return NULL; |
1428 | 1421 | ||
1429 | out_sock_release_nosk: | 1422 | out_sock_release_nosk: |
@@ -1436,10 +1429,7 @@ EXPORT_SYMBOL(netlink_kernel_create); | |||
1436 | void | 1429 | void |
1437 | netlink_kernel_release(struct sock *sk) | 1430 | netlink_kernel_release(struct sock *sk) |
1438 | { | 1431 | { |
1439 | if (sk == NULL || sk->sk_socket == NULL) | 1432 | sk_release_kernel(sk); |
1440 | return; | ||
1441 | |||
1442 | __netlink_release(sk); | ||
1443 | } | 1433 | } |
1444 | EXPORT_SYMBOL(netlink_kernel_release); | 1434 | EXPORT_SYMBOL(netlink_kernel_release); |
1445 | 1435 | ||
@@ -1552,8 +1542,13 @@ static int netlink_dump(struct sock *sk) | |||
1552 | 1542 | ||
1553 | if (len > 0) { | 1543 | if (len > 0) { |
1554 | mutex_unlock(nlk->cb_mutex); | 1544 | mutex_unlock(nlk->cb_mutex); |
1555 | skb_queue_tail(&sk->sk_receive_queue, skb); | 1545 | |
1556 | sk->sk_data_ready(sk, len); | 1546 | if (sk_filter(sk, skb)) |
1547 | kfree_skb(skb); | ||
1548 | else { | ||
1549 | skb_queue_tail(&sk->sk_receive_queue, skb); | ||
1550 | sk->sk_data_ready(sk, skb->len); | ||
1551 | } | ||
1557 | return 0; | 1552 | return 0; |
1558 | } | 1553 | } |
1559 | 1554 | ||
@@ -1563,8 +1558,12 @@ static int netlink_dump(struct sock *sk) | |||
1563 | 1558 | ||
1564 | memcpy(nlmsg_data(nlh), &len, sizeof(len)); | 1559 | memcpy(nlmsg_data(nlh), &len, sizeof(len)); |
1565 | 1560 | ||
1566 | skb_queue_tail(&sk->sk_receive_queue, skb); | 1561 | if (sk_filter(sk, skb)) |
1567 | sk->sk_data_ready(sk, skb->len); | 1562 | kfree_skb(skb); |
1563 | else { | ||
1564 | skb_queue_tail(&sk->sk_receive_queue, skb); | ||
1565 | sk->sk_data_ready(sk, skb->len); | ||
1566 | } | ||
1568 | 1567 | ||
1569 | if (cb->done) | 1568 | if (cb->done) |
1570 | cb->done(cb); | 1569 | cb->done(cb); |
@@ -1601,7 +1600,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, | |||
1601 | atomic_inc(&skb->users); | 1600 | atomic_inc(&skb->users); |
1602 | cb->skb = skb; | 1601 | cb->skb = skb; |
1603 | 1602 | ||
1604 | sk = netlink_lookup(ssk->sk_net, ssk->sk_protocol, NETLINK_CB(skb).pid); | 1603 | sk = netlink_lookup(sock_net(ssk), ssk->sk_protocol, NETLINK_CB(skb).pid); |
1605 | if (sk == NULL) { | 1604 | if (sk == NULL) { |
1606 | netlink_destroy_callback(cb); | 1605 | netlink_destroy_callback(cb); |
1607 | return -ECONNREFUSED; | 1606 | return -ECONNREFUSED; |
@@ -1643,7 +1642,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) | |||
1643 | if (!skb) { | 1642 | if (!skb) { |
1644 | struct sock *sk; | 1643 | struct sock *sk; |
1645 | 1644 | ||
1646 | sk = netlink_lookup(in_skb->sk->sk_net, | 1645 | sk = netlink_lookup(sock_net(in_skb->sk), |
1647 | in_skb->sk->sk_protocol, | 1646 | in_skb->sk->sk_protocol, |
1648 | NETLINK_CB(in_skb).pid); | 1647 | NETLINK_CB(in_skb).pid); |
1649 | if (sk) { | 1648 | if (sk) { |
@@ -1758,7 +1757,7 @@ static struct sock *netlink_seq_socket_idx(struct seq_file *seq, loff_t pos) | |||
1758 | 1757 | ||
1759 | for (j = 0; j <= hash->mask; j++) { | 1758 | for (j = 0; j <= hash->mask; j++) { |
1760 | sk_for_each(s, node, &hash->table[j]) { | 1759 | sk_for_each(s, node, &hash->table[j]) { |
1761 | if (iter->p.net != s->sk_net) | 1760 | if (sock_net(s) != seq_file_net(seq)) |
1762 | continue; | 1761 | continue; |
1763 | if (off == pos) { | 1762 | if (off == pos) { |
1764 | iter->link = i; | 1763 | iter->link = i; |
@@ -1794,7 +1793,7 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
1794 | s = v; | 1793 | s = v; |
1795 | do { | 1794 | do { |
1796 | s = sk_next(s); | 1795 | s = sk_next(s); |
1797 | } while (s && (iter->p.net != s->sk_net)); | 1796 | } while (s && sock_net(s) != seq_file_net(seq)); |
1798 | if (s) | 1797 | if (s) |
1799 | return s; | 1798 | return s; |
1800 | 1799 | ||
@@ -1806,7 +1805,7 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
1806 | 1805 | ||
1807 | for (; j <= hash->mask; j++) { | 1806 | for (; j <= hash->mask; j++) { |
1808 | s = sk_head(&hash->table[j]); | 1807 | s = sk_head(&hash->table[j]); |
1809 | while (s && (iter->p.net != s->sk_net)) | 1808 | while (s && sock_net(s) != seq_file_net(seq)) |
1810 | s = sk_next(s); | 1809 | s = sk_next(s); |
1811 | if (s) { | 1810 | if (s) { |
1812 | iter->link = i; | 1811 | iter->link = i; |