diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/802/garp.c | 18 | ||||
-rw-r--r-- | net/802/stp.c | 4 | ||||
-rw-r--r-- | net/8021q/vlan.c | 6 | ||||
-rw-r--r-- | net/core/dev.c | 16 | ||||
-rw-r--r-- | net/core/filter.c | 4 | ||||
-rw-r--r-- | net/core/net-sysfs.c | 20 | ||||
-rw-r--r-- | net/core/net_namespace.c | 4 | ||||
-rw-r--r-- | net/core/pktgen.c | 30 | ||||
-rw-r--r-- | net/core/sock.c | 2 | ||||
-rw-r--r-- | net/core/sysctl_net_core.c | 3 | ||||
-rw-r--r-- | net/ipv4/gre.c | 5 | ||||
-rw-r--r-- | net/ipv4/ip_sockglue.c | 10 | ||||
-rw-r--r-- | net/ipv4/udp.c | 2 | ||||
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 1 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 4 | ||||
-rw-r--r-- | net/ipv6/netfilter/Kconfig | 5 | ||||
-rw-r--r-- | net/ipv6/netfilter/Makefile | 5 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_reasm.c | 5 | ||||
-rw-r--r-- | net/ipv6/raw.c | 2 | ||||
-rw-r--r-- | net/ipv6/tunnel6.c | 24 | ||||
-rw-r--r-- | net/ipv6/udp.c | 2 | ||||
-rw-r--r-- | net/l2tp/l2tp_core.c | 53 | ||||
-rw-r--r-- | net/l2tp/l2tp_core.h | 33 | ||||
-rw-r--r-- | net/l2tp/l2tp_ip.c | 2 | ||||
-rw-r--r-- | net/netfilter/Kconfig | 2 | ||||
-rw-r--r-- | net/netfilter/xt_TPROXY.c | 10 | ||||
-rw-r--r-- | net/netfilter/xt_socket.c | 12 | ||||
-rw-r--r-- | net/netlink/af_netlink.c | 65 |
28 files changed, 185 insertions, 164 deletions
diff --git a/net/802/garp.c b/net/802/garp.c index 941f2a324d3a..c1df2dad8c6b 100644 --- a/net/802/garp.c +++ b/net/802/garp.c | |||
@@ -346,8 +346,8 @@ int garp_request_join(const struct net_device *dev, | |||
346 | const struct garp_application *appl, | 346 | const struct garp_application *appl, |
347 | const void *data, u8 len, u8 type) | 347 | const void *data, u8 len, u8 type) |
348 | { | 348 | { |
349 | struct garp_port *port = dev->garp_port; | 349 | struct garp_port *port = rtnl_dereference(dev->garp_port); |
350 | struct garp_applicant *app = port->applicants[appl->type]; | 350 | struct garp_applicant *app = rtnl_dereference(port->applicants[appl->type]); |
351 | struct garp_attr *attr; | 351 | struct garp_attr *attr; |
352 | 352 | ||
353 | spin_lock_bh(&app->lock); | 353 | spin_lock_bh(&app->lock); |
@@ -366,8 +366,8 @@ void garp_request_leave(const struct net_device *dev, | |||
366 | const struct garp_application *appl, | 366 | const struct garp_application *appl, |
367 | const void *data, u8 len, u8 type) | 367 | const void *data, u8 len, u8 type) |
368 | { | 368 | { |
369 | struct garp_port *port = dev->garp_port; | 369 | struct garp_port *port = rtnl_dereference(dev->garp_port); |
370 | struct garp_applicant *app = port->applicants[appl->type]; | 370 | struct garp_applicant *app = rtnl_dereference(port->applicants[appl->type]); |
371 | struct garp_attr *attr; | 371 | struct garp_attr *attr; |
372 | 372 | ||
373 | spin_lock_bh(&app->lock); | 373 | spin_lock_bh(&app->lock); |
@@ -546,11 +546,11 @@ static int garp_init_port(struct net_device *dev) | |||
546 | 546 | ||
547 | static void garp_release_port(struct net_device *dev) | 547 | static void garp_release_port(struct net_device *dev) |
548 | { | 548 | { |
549 | struct garp_port *port = dev->garp_port; | 549 | struct garp_port *port = rtnl_dereference(dev->garp_port); |
550 | unsigned int i; | 550 | unsigned int i; |
551 | 551 | ||
552 | for (i = 0; i <= GARP_APPLICATION_MAX; i++) { | 552 | for (i = 0; i <= GARP_APPLICATION_MAX; i++) { |
553 | if (port->applicants[i]) | 553 | if (rtnl_dereference(port->applicants[i])) |
554 | return; | 554 | return; |
555 | } | 555 | } |
556 | rcu_assign_pointer(dev->garp_port, NULL); | 556 | rcu_assign_pointer(dev->garp_port, NULL); |
@@ -565,7 +565,7 @@ int garp_init_applicant(struct net_device *dev, struct garp_application *appl) | |||
565 | 565 | ||
566 | ASSERT_RTNL(); | 566 | ASSERT_RTNL(); |
567 | 567 | ||
568 | if (!dev->garp_port) { | 568 | if (!rtnl_dereference(dev->garp_port)) { |
569 | err = garp_init_port(dev); | 569 | err = garp_init_port(dev); |
570 | if (err < 0) | 570 | if (err < 0) |
571 | goto err1; | 571 | goto err1; |
@@ -601,8 +601,8 @@ EXPORT_SYMBOL_GPL(garp_init_applicant); | |||
601 | 601 | ||
602 | void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl) | 602 | void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl) |
603 | { | 603 | { |
604 | struct garp_port *port = dev->garp_port; | 604 | struct garp_port *port = rtnl_dereference(dev->garp_port); |
605 | struct garp_applicant *app = port->applicants[appl->type]; | 605 | struct garp_applicant *app = rtnl_dereference(port->applicants[appl->type]); |
606 | 606 | ||
607 | ASSERT_RTNL(); | 607 | ASSERT_RTNL(); |
608 | 608 | ||
diff --git a/net/802/stp.c b/net/802/stp.c index 53c8f77f0ccd..978c30b1b36b 100644 --- a/net/802/stp.c +++ b/net/802/stp.c | |||
@@ -21,8 +21,8 @@ | |||
21 | #define GARP_ADDR_MAX 0x2F | 21 | #define GARP_ADDR_MAX 0x2F |
22 | #define GARP_ADDR_RANGE (GARP_ADDR_MAX - GARP_ADDR_MIN) | 22 | #define GARP_ADDR_RANGE (GARP_ADDR_MAX - GARP_ADDR_MIN) |
23 | 23 | ||
24 | static const struct stp_proto *garp_protos[GARP_ADDR_RANGE + 1] __read_mostly; | 24 | static const struct stp_proto __rcu *garp_protos[GARP_ADDR_RANGE + 1] __read_mostly; |
25 | static const struct stp_proto *stp_proto __read_mostly; | 25 | static const struct stp_proto __rcu *stp_proto __read_mostly; |
26 | 26 | ||
27 | static struct llc_sap *sap __read_mostly; | 27 | static struct llc_sap *sap __read_mostly; |
28 | static unsigned int sap_registered; | 28 | static unsigned int sap_registered; |
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 05b867e43757..52077ca22072 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -112,7 +112,7 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) | |||
112 | 112 | ||
113 | ASSERT_RTNL(); | 113 | ASSERT_RTNL(); |
114 | 114 | ||
115 | grp = real_dev->vlgrp; | 115 | grp = rtnl_dereference(real_dev->vlgrp); |
116 | BUG_ON(!grp); | 116 | BUG_ON(!grp); |
117 | 117 | ||
118 | /* Take it out of our own structures, but be sure to interlock with | 118 | /* Take it out of our own structures, but be sure to interlock with |
@@ -177,7 +177,7 @@ int register_vlan_dev(struct net_device *dev) | |||
177 | struct vlan_group *grp, *ngrp = NULL; | 177 | struct vlan_group *grp, *ngrp = NULL; |
178 | int err; | 178 | int err; |
179 | 179 | ||
180 | grp = real_dev->vlgrp; | 180 | grp = rtnl_dereference(real_dev->vlgrp); |
181 | if (!grp) { | 181 | if (!grp) { |
182 | ngrp = grp = vlan_group_alloc(real_dev); | 182 | ngrp = grp = vlan_group_alloc(real_dev); |
183 | if (!grp) | 183 | if (!grp) |
@@ -385,7 +385,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
385 | dev->netdev_ops->ndo_vlan_rx_add_vid(dev, 0); | 385 | dev->netdev_ops->ndo_vlan_rx_add_vid(dev, 0); |
386 | } | 386 | } |
387 | 387 | ||
388 | grp = dev->vlgrp; | 388 | grp = rtnl_dereference(dev->vlgrp); |
389 | if (!grp) | 389 | if (!grp) |
390 | goto out; | 390 | goto out; |
391 | 391 | ||
diff --git a/net/core/dev.c b/net/core/dev.c index 78b5a89b0f40..e8a8dc19365b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2213,7 +2213,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, | |||
2213 | } | 2213 | } |
2214 | 2214 | ||
2215 | static DEFINE_PER_CPU(int, xmit_recursion); | 2215 | static DEFINE_PER_CPU(int, xmit_recursion); |
2216 | #define RECURSION_LIMIT 3 | 2216 | #define RECURSION_LIMIT 10 |
2217 | 2217 | ||
2218 | /** | 2218 | /** |
2219 | * dev_queue_xmit - transmit a buffer | 2219 | * dev_queue_xmit - transmit a buffer |
@@ -2413,7 +2413,7 @@ EXPORT_SYMBOL(__skb_get_rxhash); | |||
2413 | #ifdef CONFIG_RPS | 2413 | #ifdef CONFIG_RPS |
2414 | 2414 | ||
2415 | /* One global table that all flow-based protocols share. */ | 2415 | /* One global table that all flow-based protocols share. */ |
2416 | struct rps_sock_flow_table *rps_sock_flow_table __read_mostly; | 2416 | struct rps_sock_flow_table __rcu *rps_sock_flow_table __read_mostly; |
2417 | EXPORT_SYMBOL(rps_sock_flow_table); | 2417 | EXPORT_SYMBOL(rps_sock_flow_table); |
2418 | 2418 | ||
2419 | /* | 2419 | /* |
@@ -2425,7 +2425,7 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, | |||
2425 | struct rps_dev_flow **rflowp) | 2425 | struct rps_dev_flow **rflowp) |
2426 | { | 2426 | { |
2427 | struct netdev_rx_queue *rxqueue; | 2427 | struct netdev_rx_queue *rxqueue; |
2428 | struct rps_map *map = NULL; | 2428 | struct rps_map *map; |
2429 | struct rps_dev_flow_table *flow_table; | 2429 | struct rps_dev_flow_table *flow_table; |
2430 | struct rps_sock_flow_table *sock_flow_table; | 2430 | struct rps_sock_flow_table *sock_flow_table; |
2431 | int cpu = -1; | 2431 | int cpu = -1; |
@@ -2444,15 +2444,15 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, | |||
2444 | } else | 2444 | } else |
2445 | rxqueue = dev->_rx; | 2445 | rxqueue = dev->_rx; |
2446 | 2446 | ||
2447 | if (rxqueue->rps_map) { | 2447 | map = rcu_dereference(rxqueue->rps_map); |
2448 | map = rcu_dereference(rxqueue->rps_map); | 2448 | if (map) { |
2449 | if (map && map->len == 1) { | 2449 | if (map->len == 1) { |
2450 | tcpu = map->cpus[0]; | 2450 | tcpu = map->cpus[0]; |
2451 | if (cpu_online(tcpu)) | 2451 | if (cpu_online(tcpu)) |
2452 | cpu = tcpu; | 2452 | cpu = tcpu; |
2453 | goto done; | 2453 | goto done; |
2454 | } | 2454 | } |
2455 | } else if (!rxqueue->rps_flow_table) { | 2455 | } else if (!rcu_dereference_raw(rxqueue->rps_flow_table)) { |
2456 | goto done; | 2456 | goto done; |
2457 | } | 2457 | } |
2458 | 2458 | ||
@@ -5416,7 +5416,7 @@ void netdev_run_todo(void) | |||
5416 | /* paranoia */ | 5416 | /* paranoia */ |
5417 | BUG_ON(netdev_refcnt_read(dev)); | 5417 | BUG_ON(netdev_refcnt_read(dev)); |
5418 | WARN_ON(rcu_dereference_raw(dev->ip_ptr)); | 5418 | WARN_ON(rcu_dereference_raw(dev->ip_ptr)); |
5419 | WARN_ON(dev->ip6_ptr); | 5419 | WARN_ON(rcu_dereference_raw(dev->ip6_ptr)); |
5420 | WARN_ON(dev->dn_ptr); | 5420 | WARN_ON(dev->dn_ptr); |
5421 | 5421 | ||
5422 | if (dev->destructor) | 5422 | if (dev->destructor) |
diff --git a/net/core/filter.c b/net/core/filter.c index 7adf50352918..7beaec36b541 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -89,8 +89,8 @@ int sk_filter(struct sock *sk, struct sk_buff *skb) | |||
89 | rcu_read_lock_bh(); | 89 | rcu_read_lock_bh(); |
90 | filter = rcu_dereference_bh(sk->sk_filter); | 90 | filter = rcu_dereference_bh(sk->sk_filter); |
91 | if (filter) { | 91 | if (filter) { |
92 | unsigned int pkt_len = sk_run_filter(skb, filter->insns, | 92 | unsigned int pkt_len = sk_run_filter(skb, filter->insns, filter->len); |
93 | filter->len); | 93 | |
94 | err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM; | 94 | err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM; |
95 | } | 95 | } |
96 | rcu_read_unlock_bh(); | 96 | rcu_read_unlock_bh(); |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index b143173e3eb2..a5ff5a89f376 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -598,7 +598,8 @@ static ssize_t store_rps_map(struct netdev_rx_queue *queue, | |||
598 | } | 598 | } |
599 | 599 | ||
600 | spin_lock(&rps_map_lock); | 600 | spin_lock(&rps_map_lock); |
601 | old_map = queue->rps_map; | 601 | old_map = rcu_dereference_protected(queue->rps_map, |
602 | lockdep_is_held(&rps_map_lock)); | ||
602 | rcu_assign_pointer(queue->rps_map, map); | 603 | rcu_assign_pointer(queue->rps_map, map); |
603 | spin_unlock(&rps_map_lock); | 604 | spin_unlock(&rps_map_lock); |
604 | 605 | ||
@@ -677,7 +678,8 @@ static ssize_t store_rps_dev_flow_table_cnt(struct netdev_rx_queue *queue, | |||
677 | table = NULL; | 678 | table = NULL; |
678 | 679 | ||
679 | spin_lock(&rps_dev_flow_lock); | 680 | spin_lock(&rps_dev_flow_lock); |
680 | old_table = queue->rps_flow_table; | 681 | old_table = rcu_dereference_protected(queue->rps_flow_table, |
682 | lockdep_is_held(&rps_dev_flow_lock)); | ||
681 | rcu_assign_pointer(queue->rps_flow_table, table); | 683 | rcu_assign_pointer(queue->rps_flow_table, table); |
682 | spin_unlock(&rps_dev_flow_lock); | 684 | spin_unlock(&rps_dev_flow_lock); |
683 | 685 | ||
@@ -705,13 +707,17 @@ static void rx_queue_release(struct kobject *kobj) | |||
705 | { | 707 | { |
706 | struct netdev_rx_queue *queue = to_rx_queue(kobj); | 708 | struct netdev_rx_queue *queue = to_rx_queue(kobj); |
707 | struct netdev_rx_queue *first = queue->first; | 709 | struct netdev_rx_queue *first = queue->first; |
710 | struct rps_map *map; | ||
711 | struct rps_dev_flow_table *flow_table; | ||
708 | 712 | ||
709 | if (queue->rps_map) | ||
710 | call_rcu(&queue->rps_map->rcu, rps_map_release); | ||
711 | 713 | ||
712 | if (queue->rps_flow_table) | 714 | map = rcu_dereference_raw(queue->rps_map); |
713 | call_rcu(&queue->rps_flow_table->rcu, | 715 | if (map) |
714 | rps_dev_flow_table_release); | 716 | call_rcu(&map->rcu, rps_map_release); |
717 | |||
718 | flow_table = rcu_dereference_raw(queue->rps_flow_table); | ||
719 | if (flow_table) | ||
720 | call_rcu(&flow_table->rcu, rps_dev_flow_table_release); | ||
715 | 721 | ||
716 | if (atomic_dec_and_test(&first->count)) | 722 | if (atomic_dec_and_test(&first->count)) |
717 | kfree(first); | 723 | kfree(first); |
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index c988e685433a..3f860261c5ee 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
@@ -42,7 +42,9 @@ static int net_assign_generic(struct net *net, int id, void *data) | |||
42 | BUG_ON(!mutex_is_locked(&net_mutex)); | 42 | BUG_ON(!mutex_is_locked(&net_mutex)); |
43 | BUG_ON(id == 0); | 43 | BUG_ON(id == 0); |
44 | 44 | ||
45 | ng = old_ng = net->gen; | 45 | old_ng = rcu_dereference_protected(net->gen, |
46 | lockdep_is_held(&net_mutex)); | ||
47 | ng = old_ng; | ||
46 | if (old_ng->len >= id) | 48 | if (old_ng->len >= id) |
47 | goto assign; | 49 | goto assign; |
48 | 50 | ||
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 2c0df0f95b3d..679b797d06b1 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -771,10 +771,10 @@ done: | |||
771 | static unsigned long num_arg(const char __user * user_buffer, | 771 | static unsigned long num_arg(const char __user * user_buffer, |
772 | unsigned long maxlen, unsigned long *num) | 772 | unsigned long maxlen, unsigned long *num) |
773 | { | 773 | { |
774 | int i = 0; | 774 | int i; |
775 | *num = 0; | 775 | *num = 0; |
776 | 776 | ||
777 | for (; i < maxlen; i++) { | 777 | for (i = 0; i < maxlen; i++) { |
778 | char c; | 778 | char c; |
779 | if (get_user(c, &user_buffer[i])) | 779 | if (get_user(c, &user_buffer[i])) |
780 | return -EFAULT; | 780 | return -EFAULT; |
@@ -789,9 +789,9 @@ static unsigned long num_arg(const char __user * user_buffer, | |||
789 | 789 | ||
790 | static int strn_len(const char __user * user_buffer, unsigned int maxlen) | 790 | static int strn_len(const char __user * user_buffer, unsigned int maxlen) |
791 | { | 791 | { |
792 | int i = 0; | 792 | int i; |
793 | 793 | ||
794 | for (; i < maxlen; i++) { | 794 | for (i = 0; i < maxlen; i++) { |
795 | char c; | 795 | char c; |
796 | if (get_user(c, &user_buffer[i])) | 796 | if (get_user(c, &user_buffer[i])) |
797 | return -EFAULT; | 797 | return -EFAULT; |
@@ -846,7 +846,7 @@ static ssize_t pktgen_if_write(struct file *file, | |||
846 | { | 846 | { |
847 | struct seq_file *seq = file->private_data; | 847 | struct seq_file *seq = file->private_data; |
848 | struct pktgen_dev *pkt_dev = seq->private; | 848 | struct pktgen_dev *pkt_dev = seq->private; |
849 | int i = 0, max, len; | 849 | int i, max, len; |
850 | char name[16], valstr[32]; | 850 | char name[16], valstr[32]; |
851 | unsigned long value = 0; | 851 | unsigned long value = 0; |
852 | char *pg_result = NULL; | 852 | char *pg_result = NULL; |
@@ -860,13 +860,13 @@ static ssize_t pktgen_if_write(struct file *file, | |||
860 | return -EINVAL; | 860 | return -EINVAL; |
861 | } | 861 | } |
862 | 862 | ||
863 | max = count - i; | 863 | max = count; |
864 | tmp = count_trail_chars(&user_buffer[i], max); | 864 | tmp = count_trail_chars(user_buffer, max); |
865 | if (tmp < 0) { | 865 | if (tmp < 0) { |
866 | pr_warning("illegal format\n"); | 866 | pr_warning("illegal format\n"); |
867 | return tmp; | 867 | return tmp; |
868 | } | 868 | } |
869 | i += tmp; | 869 | i = tmp; |
870 | 870 | ||
871 | /* Read variable name */ | 871 | /* Read variable name */ |
872 | 872 | ||
@@ -1764,7 +1764,7 @@ static ssize_t pktgen_thread_write(struct file *file, | |||
1764 | { | 1764 | { |
1765 | struct seq_file *seq = file->private_data; | 1765 | struct seq_file *seq = file->private_data; |
1766 | struct pktgen_thread *t = seq->private; | 1766 | struct pktgen_thread *t = seq->private; |
1767 | int i = 0, max, len, ret; | 1767 | int i, max, len, ret; |
1768 | char name[40]; | 1768 | char name[40]; |
1769 | char *pg_result; | 1769 | char *pg_result; |
1770 | 1770 | ||
@@ -1773,12 +1773,12 @@ static ssize_t pktgen_thread_write(struct file *file, | |||
1773 | return -EINVAL; | 1773 | return -EINVAL; |
1774 | } | 1774 | } |
1775 | 1775 | ||
1776 | max = count - i; | 1776 | max = count; |
1777 | len = count_trail_chars(&user_buffer[i], max); | 1777 | len = count_trail_chars(user_buffer, max); |
1778 | if (len < 0) | 1778 | if (len < 0) |
1779 | return len; | 1779 | return len; |
1780 | 1780 | ||
1781 | i += len; | 1781 | i = len; |
1782 | 1782 | ||
1783 | /* Read variable name */ | 1783 | /* Read variable name */ |
1784 | 1784 | ||
@@ -1975,7 +1975,7 @@ static struct net_device *pktgen_dev_get_by_name(struct pktgen_dev *pkt_dev, | |||
1975 | const char *ifname) | 1975 | const char *ifname) |
1976 | { | 1976 | { |
1977 | char b[IFNAMSIZ+5]; | 1977 | char b[IFNAMSIZ+5]; |
1978 | int i = 0; | 1978 | int i; |
1979 | 1979 | ||
1980 | for (i = 0; ifname[i] != '@'; i++) { | 1980 | for (i = 0; ifname[i] != '@'; i++) { |
1981 | if (i == IFNAMSIZ) | 1981 | if (i == IFNAMSIZ) |
@@ -2519,8 +2519,8 @@ static void free_SAs(struct pktgen_dev *pkt_dev) | |||
2519 | { | 2519 | { |
2520 | if (pkt_dev->cflows) { | 2520 | if (pkt_dev->cflows) { |
2521 | /* let go of the SAs if we have them */ | 2521 | /* let go of the SAs if we have them */ |
2522 | int i = 0; | 2522 | int i; |
2523 | for (; i < pkt_dev->cflows; i++) { | 2523 | for (i = 0; i < pkt_dev->cflows; i++) { |
2524 | struct xfrm_state *x = pkt_dev->flows[i].x; | 2524 | struct xfrm_state *x = pkt_dev->flows[i].x; |
2525 | if (x) { | 2525 | if (x) { |
2526 | xfrm_state_put(x); | 2526 | xfrm_state_put(x); |
diff --git a/net/core/sock.c b/net/core/sock.c index 11db43632df8..3eed5424e659 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -1225,7 +1225,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) | |||
1225 | sock_reset_flag(newsk, SOCK_DONE); | 1225 | sock_reset_flag(newsk, SOCK_DONE); |
1226 | skb_queue_head_init(&newsk->sk_error_queue); | 1226 | skb_queue_head_init(&newsk->sk_error_queue); |
1227 | 1227 | ||
1228 | filter = newsk->sk_filter; | 1228 | filter = rcu_dereference_protected(newsk->sk_filter, 1); |
1229 | if (filter != NULL) | 1229 | if (filter != NULL) |
1230 | sk_filter_charge(newsk, filter); | 1230 | sk_filter_charge(newsk, filter); |
1231 | 1231 | ||
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 01eee5d984be..385b6095fdc4 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c | |||
@@ -34,7 +34,8 @@ static int rps_sock_flow_sysctl(ctl_table *table, int write, | |||
34 | 34 | ||
35 | mutex_lock(&sock_flow_mutex); | 35 | mutex_lock(&sock_flow_mutex); |
36 | 36 | ||
37 | orig_sock_table = rps_sock_flow_table; | 37 | orig_sock_table = rcu_dereference_protected(rps_sock_flow_table, |
38 | lockdep_is_held(&sock_flow_mutex)); | ||
38 | size = orig_size = orig_sock_table ? orig_sock_table->mask + 1 : 0; | 39 | size = orig_size = orig_sock_table ? orig_sock_table->mask + 1 : 0; |
39 | 40 | ||
40 | ret = proc_dointvec(&tmp, write, buffer, lenp, ppos); | 41 | ret = proc_dointvec(&tmp, write, buffer, lenp, ppos); |
diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c index caea6885fdbd..c6933f2ea310 100644 --- a/net/ipv4/gre.c +++ b/net/ipv4/gre.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <net/gre.h> | 22 | #include <net/gre.h> |
23 | 23 | ||
24 | 24 | ||
25 | static const struct gre_protocol *gre_proto[GREPROTO_MAX] __read_mostly; | 25 | static const struct gre_protocol __rcu *gre_proto[GREPROTO_MAX] __read_mostly; |
26 | static DEFINE_SPINLOCK(gre_proto_lock); | 26 | static DEFINE_SPINLOCK(gre_proto_lock); |
27 | 27 | ||
28 | int gre_add_protocol(const struct gre_protocol *proto, u8 version) | 28 | int gre_add_protocol(const struct gre_protocol *proto, u8 version) |
@@ -51,7 +51,8 @@ int gre_del_protocol(const struct gre_protocol *proto, u8 version) | |||
51 | goto err_out; | 51 | goto err_out; |
52 | 52 | ||
53 | spin_lock(&gre_proto_lock); | 53 | spin_lock(&gre_proto_lock); |
54 | if (gre_proto[version] != proto) | 54 | if (rcu_dereference_protected(gre_proto[version], |
55 | lockdep_is_held(&gre_proto_lock)) != proto) | ||
55 | goto err_out_unlock; | 56 | goto err_out_unlock; |
56 | rcu_assign_pointer(gre_proto[version], NULL); | 57 | rcu_assign_pointer(gre_proto[version], NULL); |
57 | spin_unlock(&gre_proto_lock); | 58 | spin_unlock(&gre_proto_lock); |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 64b70ad162e3..3948c86e59ca 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
@@ -238,7 +238,7 @@ int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc) | |||
238 | but receiver should be enough clever f.e. to forward mtrace requests, | 238 | but receiver should be enough clever f.e. to forward mtrace requests, |
239 | sent to multicast group to reach destination designated router. | 239 | sent to multicast group to reach destination designated router. |
240 | */ | 240 | */ |
241 | struct ip_ra_chain *ip_ra_chain; | 241 | struct ip_ra_chain __rcu *ip_ra_chain; |
242 | static DEFINE_SPINLOCK(ip_ra_lock); | 242 | static DEFINE_SPINLOCK(ip_ra_lock); |
243 | 243 | ||
244 | 244 | ||
@@ -253,7 +253,8 @@ static void ip_ra_destroy_rcu(struct rcu_head *head) | |||
253 | int ip_ra_control(struct sock *sk, unsigned char on, | 253 | int ip_ra_control(struct sock *sk, unsigned char on, |
254 | void (*destructor)(struct sock *)) | 254 | void (*destructor)(struct sock *)) |
255 | { | 255 | { |
256 | struct ip_ra_chain *ra, *new_ra, **rap; | 256 | struct ip_ra_chain *ra, *new_ra; |
257 | struct ip_ra_chain __rcu **rap; | ||
257 | 258 | ||
258 | if (sk->sk_type != SOCK_RAW || inet_sk(sk)->inet_num == IPPROTO_RAW) | 259 | if (sk->sk_type != SOCK_RAW || inet_sk(sk)->inet_num == IPPROTO_RAW) |
259 | return -EINVAL; | 260 | return -EINVAL; |
@@ -261,7 +262,10 @@ int ip_ra_control(struct sock *sk, unsigned char on, | |||
261 | new_ra = on ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL; | 262 | new_ra = on ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL; |
262 | 263 | ||
263 | spin_lock_bh(&ip_ra_lock); | 264 | spin_lock_bh(&ip_ra_lock); |
264 | for (rap = &ip_ra_chain; (ra = *rap) != NULL; rap = &ra->next) { | 265 | for (rap = &ip_ra_chain; |
266 | (ra = rcu_dereference_protected(*rap, | ||
267 | lockdep_is_held(&ip_ra_lock))) != NULL; | ||
268 | rap = &ra->next) { | ||
265 | if (ra->sk == sk) { | 269 | if (ra->sk == sk) { |
266 | if (on) { | 270 | if (on) { |
267 | spin_unlock_bh(&ip_ra_lock); | 271 | spin_unlock_bh(&ip_ra_lock); |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index b3f7e8cf18ac..28cb2d733a3c 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1413,7 +1413,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
1413 | } | 1413 | } |
1414 | } | 1414 | } |
1415 | 1415 | ||
1416 | if (sk->sk_filter) { | 1416 | if (rcu_dereference_raw(sk->sk_filter)) { |
1417 | if (udp_lib_checksum_complete(skb)) | 1417 | if (udp_lib_checksum_complete(skb)) |
1418 | goto drop; | 1418 | goto drop; |
1419 | } | 1419 | } |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index c2c0f89397b1..38b9a56c173f 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -1371,6 +1371,7 @@ static void ip6_tnl_dev_setup(struct net_device *dev) | |||
1371 | dev->flags |= IFF_NOARP; | 1371 | dev->flags |= IFF_NOARP; |
1372 | dev->addr_len = sizeof(struct in6_addr); | 1372 | dev->addr_len = sizeof(struct in6_addr); |
1373 | dev->features |= NETIF_F_NETNS_LOCAL; | 1373 | dev->features |= NETIF_F_NETNS_LOCAL; |
1374 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; | ||
1374 | } | 1375 | } |
1375 | 1376 | ||
1376 | 1377 | ||
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 0553867a317f..d1770e061c08 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -343,6 +343,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
343 | break; | 343 | break; |
344 | 344 | ||
345 | case IPV6_TRANSPARENT: | 345 | case IPV6_TRANSPARENT: |
346 | if (!capable(CAP_NET_ADMIN)) { | ||
347 | retv = -EPERM; | ||
348 | break; | ||
349 | } | ||
346 | if (optlen < sizeof(int)) | 350 | if (optlen < sizeof(int)) |
347 | goto e_inval; | 351 | goto e_inval; |
348 | /* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */ | 352 | /* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */ |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 44d2eeac089b..448464844a25 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -5,10 +5,15 @@ | |||
5 | menu "IPv6: Netfilter Configuration" | 5 | menu "IPv6: Netfilter Configuration" |
6 | depends on INET && IPV6 && NETFILTER | 6 | depends on INET && IPV6 && NETFILTER |
7 | 7 | ||
8 | config NF_DEFRAG_IPV6 | ||
9 | tristate | ||
10 | default n | ||
11 | |||
8 | config NF_CONNTRACK_IPV6 | 12 | config NF_CONNTRACK_IPV6 |
9 | tristate "IPv6 connection tracking support" | 13 | tristate "IPv6 connection tracking support" |
10 | depends on INET && IPV6 && NF_CONNTRACK | 14 | depends on INET && IPV6 && NF_CONNTRACK |
11 | default m if NETFILTER_ADVANCED=n | 15 | default m if NETFILTER_ADVANCED=n |
16 | select NF_DEFRAG_IPV6 | ||
12 | ---help--- | 17 | ---help--- |
13 | Connection tracking keeps a record of what packets have passed | 18 | Connection tracking keeps a record of what packets have passed |
14 | through your machine, in order to figure out how they are related | 19 | through your machine, in order to figure out how they are related |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index 3f8e4a3d83ce..0a432c9b0795 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -12,11 +12,14 @@ obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o | |||
12 | 12 | ||
13 | # objects for l3 independent conntrack | 13 | # objects for l3 independent conntrack |
14 | nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o | 14 | nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o |
15 | nf_defrag_ipv6-objs := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o | ||
16 | 15 | ||
17 | # l3 independent conntrack | 16 | # l3 independent conntrack |
18 | obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o nf_defrag_ipv6.o | 17 | obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o nf_defrag_ipv6.o |
19 | 18 | ||
19 | # defrag | ||
20 | nf_defrag_ipv6-objs := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o | ||
21 | obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o | ||
22 | |||
20 | # matches | 23 | # matches |
21 | obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o | 24 | obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o |
22 | obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o | 25 | obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 489d71b844ac..3a3f129a44cb 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -625,21 +625,24 @@ int nf_ct_frag6_init(void) | |||
625 | inet_frags_init_net(&nf_init_frags); | 625 | inet_frags_init_net(&nf_init_frags); |
626 | inet_frags_init(&nf_frags); | 626 | inet_frags_init(&nf_frags); |
627 | 627 | ||
628 | #ifdef CONFIG_SYSCTL | ||
628 | nf_ct_frag6_sysctl_header = register_sysctl_paths(nf_net_netfilter_sysctl_path, | 629 | nf_ct_frag6_sysctl_header = register_sysctl_paths(nf_net_netfilter_sysctl_path, |
629 | nf_ct_frag6_sysctl_table); | 630 | nf_ct_frag6_sysctl_table); |
630 | if (!nf_ct_frag6_sysctl_header) { | 631 | if (!nf_ct_frag6_sysctl_header) { |
631 | inet_frags_fini(&nf_frags); | 632 | inet_frags_fini(&nf_frags); |
632 | return -ENOMEM; | 633 | return -ENOMEM; |
633 | } | 634 | } |
635 | #endif | ||
634 | 636 | ||
635 | return 0; | 637 | return 0; |
636 | } | 638 | } |
637 | 639 | ||
638 | void nf_ct_frag6_cleanup(void) | 640 | void nf_ct_frag6_cleanup(void) |
639 | { | 641 | { |
642 | #ifdef CONFIG_SYSCTL | ||
640 | unregister_sysctl_table(nf_ct_frag6_sysctl_header); | 643 | unregister_sysctl_table(nf_ct_frag6_sysctl_header); |
641 | nf_ct_frag6_sysctl_header = NULL; | 644 | nf_ct_frag6_sysctl_header = NULL; |
642 | 645 | #endif | |
643 | inet_frags_fini(&nf_frags); | 646 | inet_frags_fini(&nf_frags); |
644 | 647 | ||
645 | nf_init_frags.low_thresh = 0; | 648 | nf_init_frags.low_thresh = 0; |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 45e6efb7f171..86c39526ba5e 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -373,7 +373,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, | |||
373 | 373 | ||
374 | static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb) | 374 | static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb) |
375 | { | 375 | { |
376 | if ((raw6_sk(sk)->checksum || sk->sk_filter) && | 376 | if ((raw6_sk(sk)->checksum || rcu_dereference_raw(sk->sk_filter)) && |
377 | skb_checksum_complete(skb)) { | 377 | skb_checksum_complete(skb)) { |
378 | atomic_inc(&sk->sk_drops); | 378 | atomic_inc(&sk->sk_drops); |
379 | kfree_skb(skb); | 379 | kfree_skb(skb); |
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c index d9864725d0c6..4f3cec12aa85 100644 --- a/net/ipv6/tunnel6.c +++ b/net/ipv6/tunnel6.c | |||
@@ -30,23 +30,26 @@ | |||
30 | #include <net/protocol.h> | 30 | #include <net/protocol.h> |
31 | #include <net/xfrm.h> | 31 | #include <net/xfrm.h> |
32 | 32 | ||
33 | static struct xfrm6_tunnel *tunnel6_handlers __read_mostly; | 33 | static struct xfrm6_tunnel __rcu *tunnel6_handlers __read_mostly; |
34 | static struct xfrm6_tunnel *tunnel46_handlers __read_mostly; | 34 | static struct xfrm6_tunnel __rcu *tunnel46_handlers __read_mostly; |
35 | static DEFINE_MUTEX(tunnel6_mutex); | 35 | static DEFINE_MUTEX(tunnel6_mutex); |
36 | 36 | ||
37 | int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family) | 37 | int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family) |
38 | { | 38 | { |
39 | struct xfrm6_tunnel **pprev; | 39 | struct xfrm6_tunnel __rcu **pprev; |
40 | struct xfrm6_tunnel *t; | ||
40 | int ret = -EEXIST; | 41 | int ret = -EEXIST; |
41 | int priority = handler->priority; | 42 | int priority = handler->priority; |
42 | 43 | ||
43 | mutex_lock(&tunnel6_mutex); | 44 | mutex_lock(&tunnel6_mutex); |
44 | 45 | ||
45 | for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers; | 46 | for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers; |
46 | *pprev; pprev = &(*pprev)->next) { | 47 | (t = rcu_dereference_protected(*pprev, |
47 | if ((*pprev)->priority > priority) | 48 | lockdep_is_held(&tunnel6_mutex))) != NULL; |
49 | pprev = &t->next) { | ||
50 | if (t->priority > priority) | ||
48 | break; | 51 | break; |
49 | if ((*pprev)->priority == priority) | 52 | if (t->priority == priority) |
50 | goto err; | 53 | goto err; |
51 | } | 54 | } |
52 | 55 | ||
@@ -65,14 +68,17 @@ EXPORT_SYMBOL(xfrm6_tunnel_register); | |||
65 | 68 | ||
66 | int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family) | 69 | int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family) |
67 | { | 70 | { |
68 | struct xfrm6_tunnel **pprev; | 71 | struct xfrm6_tunnel __rcu **pprev; |
72 | struct xfrm6_tunnel *t; | ||
69 | int ret = -ENOENT; | 73 | int ret = -ENOENT; |
70 | 74 | ||
71 | mutex_lock(&tunnel6_mutex); | 75 | mutex_lock(&tunnel6_mutex); |
72 | 76 | ||
73 | for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers; | 77 | for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers; |
74 | *pprev; pprev = &(*pprev)->next) { | 78 | (t = rcu_dereference_protected(*pprev, |
75 | if (*pprev == handler) { | 79 | lockdep_is_held(&tunnel6_mutex))) != NULL; |
80 | pprev = &t->next) { | ||
81 | if (t == handler) { | ||
76 | *pprev = handler->next; | 82 | *pprev = handler->next; |
77 | ret = 0; | 83 | ret = 0; |
78 | break; | 84 | break; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index c84dad432114..91def93bec85 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -527,7 +527,7 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
527 | } | 527 | } |
528 | } | 528 | } |
529 | 529 | ||
530 | if (sk->sk_filter) { | 530 | if (rcu_dereference_raw(sk->sk_filter)) { |
531 | if (udp_lib_checksum_complete(skb)) | 531 | if (udp_lib_checksum_complete(skb)) |
532 | goto drop; | 532 | goto drop; |
533 | } | 533 | } |
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 1712af1c7b3f..c64ce0a0bb03 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
@@ -111,6 +111,10 @@ struct l2tp_net { | |||
111 | spinlock_t l2tp_session_hlist_lock; | 111 | spinlock_t l2tp_session_hlist_lock; |
112 | }; | 112 | }; |
113 | 113 | ||
114 | static void l2tp_session_set_header_len(struct l2tp_session *session, int version); | ||
115 | static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel); | ||
116 | static void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel); | ||
117 | |||
114 | static inline struct l2tp_net *l2tp_pernet(struct net *net) | 118 | static inline struct l2tp_net *l2tp_pernet(struct net *net) |
115 | { | 119 | { |
116 | BUG_ON(!net); | 120 | BUG_ON(!net); |
@@ -118,6 +122,34 @@ static inline struct l2tp_net *l2tp_pernet(struct net *net) | |||
118 | return net_generic(net, l2tp_net_id); | 122 | return net_generic(net, l2tp_net_id); |
119 | } | 123 | } |
120 | 124 | ||
125 | |||
126 | /* Tunnel reference counts. Incremented per session that is added to | ||
127 | * the tunnel. | ||
128 | */ | ||
129 | static inline void l2tp_tunnel_inc_refcount_1(struct l2tp_tunnel *tunnel) | ||
130 | { | ||
131 | atomic_inc(&tunnel->ref_count); | ||
132 | } | ||
133 | |||
134 | static inline void l2tp_tunnel_dec_refcount_1(struct l2tp_tunnel *tunnel) | ||
135 | { | ||
136 | if (atomic_dec_and_test(&tunnel->ref_count)) | ||
137 | l2tp_tunnel_free(tunnel); | ||
138 | } | ||
139 | #ifdef L2TP_REFCNT_DEBUG | ||
140 | #define l2tp_tunnel_inc_refcount(_t) do { \ | ||
141 | printk(KERN_DEBUG "l2tp_tunnel_inc_refcount: %s:%d %s: cnt=%d\n", __func__, __LINE__, (_t)->name, atomic_read(&_t->ref_count)); \ | ||
142 | l2tp_tunnel_inc_refcount_1(_t); \ | ||
143 | } while (0) | ||
144 | #define l2tp_tunnel_dec_refcount(_t) do { \ | ||
145 | printk(KERN_DEBUG "l2tp_tunnel_dec_refcount: %s:%d %s: cnt=%d\n", __func__, __LINE__, (_t)->name, atomic_read(&_t->ref_count)); \ | ||
146 | l2tp_tunnel_dec_refcount_1(_t); \ | ||
147 | } while (0) | ||
148 | #else | ||
149 | #define l2tp_tunnel_inc_refcount(t) l2tp_tunnel_inc_refcount_1(t) | ||
150 | #define l2tp_tunnel_dec_refcount(t) l2tp_tunnel_dec_refcount_1(t) | ||
151 | #endif | ||
152 | |||
121 | /* Session hash global list for L2TPv3. | 153 | /* Session hash global list for L2TPv3. |
122 | * The session_id SHOULD be random according to RFC3931, but several | 154 | * The session_id SHOULD be random according to RFC3931, but several |
123 | * L2TP implementations use incrementing session_ids. So we do a real | 155 | * L2TP implementations use incrementing session_ids. So we do a real |
@@ -699,8 +731,8 @@ EXPORT_SYMBOL(l2tp_recv_common); | |||
699 | * Returns 1 if the packet was not a good data packet and could not be | 731 | * Returns 1 if the packet was not a good data packet and could not be |
700 | * forwarded. All such packets are passed up to userspace to deal with. | 732 | * forwarded. All such packets are passed up to userspace to deal with. |
701 | */ | 733 | */ |
702 | int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, | 734 | static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, |
703 | int (*payload_hook)(struct sk_buff *skb)) | 735 | int (*payload_hook)(struct sk_buff *skb)) |
704 | { | 736 | { |
705 | struct l2tp_session *session = NULL; | 737 | struct l2tp_session *session = NULL; |
706 | unsigned char *ptr, *optr; | 738 | unsigned char *ptr, *optr; |
@@ -812,7 +844,6 @@ error: | |||
812 | 844 | ||
813 | return 1; | 845 | return 1; |
814 | } | 846 | } |
815 | EXPORT_SYMBOL_GPL(l2tp_udp_recv_core); | ||
816 | 847 | ||
817 | /* UDP encapsulation receive handler. See net/ipv4/udp.c. | 848 | /* UDP encapsulation receive handler. See net/ipv4/udp.c. |
818 | * Return codes: | 849 | * Return codes: |
@@ -922,7 +953,8 @@ static int l2tp_build_l2tpv3_header(struct l2tp_session *session, void *buf) | |||
922 | return bufp - optr; | 953 | return bufp - optr; |
923 | } | 954 | } |
924 | 955 | ||
925 | int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, size_t data_len) | 956 | static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, |
957 | size_t data_len) | ||
926 | { | 958 | { |
927 | struct l2tp_tunnel *tunnel = session->tunnel; | 959 | struct l2tp_tunnel *tunnel = session->tunnel; |
928 | unsigned int len = skb->len; | 960 | unsigned int len = skb->len; |
@@ -970,7 +1002,6 @@ int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, size_t dat | |||
970 | 1002 | ||
971 | return 0; | 1003 | return 0; |
972 | } | 1004 | } |
973 | EXPORT_SYMBOL_GPL(l2tp_xmit_core); | ||
974 | 1005 | ||
975 | /* Automatically called when the skb is freed. | 1006 | /* Automatically called when the skb is freed. |
976 | */ | 1007 | */ |
@@ -1089,7 +1120,7 @@ EXPORT_SYMBOL_GPL(l2tp_xmit_skb); | |||
1089 | * The tunnel context is deleted only when all session sockets have been | 1120 | * The tunnel context is deleted only when all session sockets have been |
1090 | * closed. | 1121 | * closed. |
1091 | */ | 1122 | */ |
1092 | void l2tp_tunnel_destruct(struct sock *sk) | 1123 | static void l2tp_tunnel_destruct(struct sock *sk) |
1093 | { | 1124 | { |
1094 | struct l2tp_tunnel *tunnel; | 1125 | struct l2tp_tunnel *tunnel; |
1095 | 1126 | ||
@@ -1128,11 +1159,10 @@ void l2tp_tunnel_destruct(struct sock *sk) | |||
1128 | end: | 1159 | end: |
1129 | return; | 1160 | return; |
1130 | } | 1161 | } |
1131 | EXPORT_SYMBOL(l2tp_tunnel_destruct); | ||
1132 | 1162 | ||
1133 | /* When the tunnel is closed, all the attached sessions need to go too. | 1163 | /* When the tunnel is closed, all the attached sessions need to go too. |
1134 | */ | 1164 | */ |
1135 | void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel) | 1165 | static void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel) |
1136 | { | 1166 | { |
1137 | int hash; | 1167 | int hash; |
1138 | struct hlist_node *walk; | 1168 | struct hlist_node *walk; |
@@ -1193,12 +1223,11 @@ again: | |||
1193 | } | 1223 | } |
1194 | write_unlock_bh(&tunnel->hlist_lock); | 1224 | write_unlock_bh(&tunnel->hlist_lock); |
1195 | } | 1225 | } |
1196 | EXPORT_SYMBOL_GPL(l2tp_tunnel_closeall); | ||
1197 | 1226 | ||
1198 | /* Really kill the tunnel. | 1227 | /* Really kill the tunnel. |
1199 | * Come here only when all sessions have been cleared from the tunnel. | 1228 | * Come here only when all sessions have been cleared from the tunnel. |
1200 | */ | 1229 | */ |
1201 | void l2tp_tunnel_free(struct l2tp_tunnel *tunnel) | 1230 | static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel) |
1202 | { | 1231 | { |
1203 | struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net); | 1232 | struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net); |
1204 | 1233 | ||
@@ -1217,7 +1246,6 @@ void l2tp_tunnel_free(struct l2tp_tunnel *tunnel) | |||
1217 | atomic_dec(&l2tp_tunnel_count); | 1246 | atomic_dec(&l2tp_tunnel_count); |
1218 | kfree(tunnel); | 1247 | kfree(tunnel); |
1219 | } | 1248 | } |
1220 | EXPORT_SYMBOL_GPL(l2tp_tunnel_free); | ||
1221 | 1249 | ||
1222 | /* Create a socket for the tunnel, if one isn't set up by | 1250 | /* Create a socket for the tunnel, if one isn't set up by |
1223 | * userspace. This is used for static tunnels where there is no | 1251 | * userspace. This is used for static tunnels where there is no |
@@ -1512,7 +1540,7 @@ EXPORT_SYMBOL_GPL(l2tp_session_delete); | |||
1512 | /* We come here whenever a session's send_seq, cookie_len or | 1540 | /* We come here whenever a session's send_seq, cookie_len or |
1513 | * l2specific_len parameters are set. | 1541 | * l2specific_len parameters are set. |
1514 | */ | 1542 | */ |
1515 | void l2tp_session_set_header_len(struct l2tp_session *session, int version) | 1543 | static void l2tp_session_set_header_len(struct l2tp_session *session, int version) |
1516 | { | 1544 | { |
1517 | if (version == L2TP_HDR_VER_2) { | 1545 | if (version == L2TP_HDR_VER_2) { |
1518 | session->hdr_len = 6; | 1546 | session->hdr_len = 6; |
@@ -1525,7 +1553,6 @@ void l2tp_session_set_header_len(struct l2tp_session *session, int version) | |||
1525 | } | 1553 | } |
1526 | 1554 | ||
1527 | } | 1555 | } |
1528 | EXPORT_SYMBOL_GPL(l2tp_session_set_header_len); | ||
1529 | 1556 | ||
1530 | struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg) | 1557 | struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg) |
1531 | { | 1558 | { |
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index f0f318edd3f1..a16a48e79fab 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h | |||
@@ -231,48 +231,15 @@ extern int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_i | |||
231 | extern int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel); | 231 | extern int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel); |
232 | extern struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg); | 232 | extern struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg); |
233 | extern int l2tp_session_delete(struct l2tp_session *session); | 233 | extern int l2tp_session_delete(struct l2tp_session *session); |
234 | extern void l2tp_tunnel_free(struct l2tp_tunnel *tunnel); | ||
235 | extern void l2tp_session_free(struct l2tp_session *session); | 234 | extern void l2tp_session_free(struct l2tp_session *session); |
236 | extern void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, unsigned char *ptr, unsigned char *optr, u16 hdrflags, int length, int (*payload_hook)(struct sk_buff *skb)); | 235 | extern void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, unsigned char *ptr, unsigned char *optr, u16 hdrflags, int length, int (*payload_hook)(struct sk_buff *skb)); |
237 | extern int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, int (*payload_hook)(struct sk_buff *skb)); | ||
238 | extern int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb); | 236 | extern int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb); |
239 | 237 | ||
240 | extern int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, size_t data_len); | ||
241 | extern int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len); | 238 | extern int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len); |
242 | extern void l2tp_tunnel_destruct(struct sock *sk); | ||
243 | extern void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel); | ||
244 | extern void l2tp_session_set_header_len(struct l2tp_session *session, int version); | ||
245 | 239 | ||
246 | extern int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, const struct l2tp_nl_cmd_ops *ops); | 240 | extern int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, const struct l2tp_nl_cmd_ops *ops); |
247 | extern void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type); | 241 | extern void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type); |
248 | 242 | ||
249 | /* Tunnel reference counts. Incremented per session that is added to | ||
250 | * the tunnel. | ||
251 | */ | ||
252 | static inline void l2tp_tunnel_inc_refcount_1(struct l2tp_tunnel *tunnel) | ||
253 | { | ||
254 | atomic_inc(&tunnel->ref_count); | ||
255 | } | ||
256 | |||
257 | static inline void l2tp_tunnel_dec_refcount_1(struct l2tp_tunnel *tunnel) | ||
258 | { | ||
259 | if (atomic_dec_and_test(&tunnel->ref_count)) | ||
260 | l2tp_tunnel_free(tunnel); | ||
261 | } | ||
262 | #ifdef L2TP_REFCNT_DEBUG | ||
263 | #define l2tp_tunnel_inc_refcount(_t) do { \ | ||
264 | printk(KERN_DEBUG "l2tp_tunnel_inc_refcount: %s:%d %s: cnt=%d\n", __func__, __LINE__, (_t)->name, atomic_read(&_t->ref_count)); \ | ||
265 | l2tp_tunnel_inc_refcount_1(_t); \ | ||
266 | } while (0) | ||
267 | #define l2tp_tunnel_dec_refcount(_t) do { \ | ||
268 | printk(KERN_DEBUG "l2tp_tunnel_dec_refcount: %s:%d %s: cnt=%d\n", __func__, __LINE__, (_t)->name, atomic_read(&_t->ref_count)); \ | ||
269 | l2tp_tunnel_dec_refcount_1(_t); \ | ||
270 | } while (0) | ||
271 | #else | ||
272 | #define l2tp_tunnel_inc_refcount(t) l2tp_tunnel_inc_refcount_1(t) | ||
273 | #define l2tp_tunnel_dec_refcount(t) l2tp_tunnel_dec_refcount_1(t) | ||
274 | #endif | ||
275 | |||
276 | /* Session reference counts. Incremented when code obtains a reference | 243 | /* Session reference counts. Incremented when code obtains a reference |
277 | * to a session. | 244 | * to a session. |
278 | */ | 245 | */ |
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index 1c770c0644d1..0bf6a59545ab 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c | |||
@@ -576,7 +576,7 @@ out: | |||
576 | return copied; | 576 | return copied; |
577 | } | 577 | } |
578 | 578 | ||
579 | struct proto l2tp_ip_prot = { | 579 | static struct proto l2tp_ip_prot = { |
580 | .name = "L2TP/IP", | 580 | .name = "L2TP/IP", |
581 | .owner = THIS_MODULE, | 581 | .owner = THIS_MODULE, |
582 | .init = l2tp_ip_open, | 582 | .init = l2tp_ip_open, |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 43288259f4a1..1534f2b44caf 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -525,6 +525,7 @@ config NETFILTER_XT_TARGET_TPROXY | |||
525 | depends on NETFILTER_XTABLES | 525 | depends on NETFILTER_XTABLES |
526 | depends on NETFILTER_ADVANCED | 526 | depends on NETFILTER_ADVANCED |
527 | select NF_DEFRAG_IPV4 | 527 | select NF_DEFRAG_IPV4 |
528 | select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES | ||
528 | help | 529 | help |
529 | This option adds a `TPROXY' target, which is somewhat similar to | 530 | This option adds a `TPROXY' target, which is somewhat similar to |
530 | REDIRECT. It can only be used in the mangle table and is useful | 531 | REDIRECT. It can only be used in the mangle table and is useful |
@@ -927,6 +928,7 @@ config NETFILTER_XT_MATCH_SOCKET | |||
927 | depends on NETFILTER_ADVANCED | 928 | depends on NETFILTER_ADVANCED |
928 | depends on !NF_CONNTRACK || NF_CONNTRACK | 929 | depends on !NF_CONNTRACK || NF_CONNTRACK |
929 | select NF_DEFRAG_IPV4 | 930 | select NF_DEFRAG_IPV4 |
931 | select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES | ||
930 | help | 932 | help |
931 | This option adds a `socket' match, which can be used to match | 933 | This option adds a `socket' match, which can be used to match |
932 | packets for which a TCP or UDP socket lookup finds a valid socket. | 934 | packets for which a TCP or UDP socket lookup finds a valid socket. |
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c index 19c482caf30b..640678f47a2a 100644 --- a/net/netfilter/xt_TPROXY.c +++ b/net/netfilter/xt_TPROXY.c | |||
@@ -21,7 +21,9 @@ | |||
21 | #include <linux/netfilter_ipv4/ip_tables.h> | 21 | #include <linux/netfilter_ipv4/ip_tables.h> |
22 | 22 | ||
23 | #include <net/netfilter/ipv4/nf_defrag_ipv4.h> | 23 | #include <net/netfilter/ipv4/nf_defrag_ipv4.h> |
24 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 24 | |
25 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | ||
26 | #define XT_TPROXY_HAVE_IPV6 1 | ||
25 | #include <net/if_inet6.h> | 27 | #include <net/if_inet6.h> |
26 | #include <net/addrconf.h> | 28 | #include <net/addrconf.h> |
27 | #include <linux/netfilter_ipv6/ip6_tables.h> | 29 | #include <linux/netfilter_ipv6/ip6_tables.h> |
@@ -172,7 +174,7 @@ tproxy_tg4_v1(struct sk_buff *skb, const struct xt_action_param *par) | |||
172 | return tproxy_tg4(skb, tgi->laddr.ip, tgi->lport, tgi->mark_mask, tgi->mark_value); | 174 | return tproxy_tg4(skb, tgi->laddr.ip, tgi->lport, tgi->mark_mask, tgi->mark_value); |
173 | } | 175 | } |
174 | 176 | ||
175 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 177 | #ifdef XT_TPROXY_HAVE_IPV6 |
176 | 178 | ||
177 | static inline const struct in6_addr * | 179 | static inline const struct in6_addr * |
178 | tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr, | 180 | tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr, |
@@ -372,7 +374,7 @@ static struct xt_target tproxy_tg_reg[] __read_mostly = { | |||
372 | .hooks = 1 << NF_INET_PRE_ROUTING, | 374 | .hooks = 1 << NF_INET_PRE_ROUTING, |
373 | .me = THIS_MODULE, | 375 | .me = THIS_MODULE, |
374 | }, | 376 | }, |
375 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 377 | #ifdef XT_TPROXY_HAVE_IPV6 |
376 | { | 378 | { |
377 | .name = "TPROXY", | 379 | .name = "TPROXY", |
378 | .family = NFPROTO_IPV6, | 380 | .family = NFPROTO_IPV6, |
@@ -391,7 +393,7 @@ static struct xt_target tproxy_tg_reg[] __read_mostly = { | |||
391 | static int __init tproxy_tg_init(void) | 393 | static int __init tproxy_tg_init(void) |
392 | { | 394 | { |
393 | nf_defrag_ipv4_enable(); | 395 | nf_defrag_ipv4_enable(); |
394 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 396 | #ifdef XT_TPROXY_HAVE_IPV6 |
395 | nf_defrag_ipv6_enable(); | 397 | nf_defrag_ipv6_enable(); |
396 | #endif | 398 | #endif |
397 | 399 | ||
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c index 2dbd4c857735..d94a858dc52a 100644 --- a/net/netfilter/xt_socket.c +++ b/net/netfilter/xt_socket.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
15 | #include <linux/netfilter/x_tables.h> | 15 | #include <linux/netfilter/x_tables.h> |
16 | #include <linux/netfilter_ipv4/ip_tables.h> | 16 | #include <linux/netfilter_ipv4/ip_tables.h> |
17 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
18 | #include <net/tcp.h> | 17 | #include <net/tcp.h> |
19 | #include <net/udp.h> | 18 | #include <net/udp.h> |
20 | #include <net/icmp.h> | 19 | #include <net/icmp.h> |
@@ -22,7 +21,12 @@ | |||
22 | #include <net/inet_sock.h> | 21 | #include <net/inet_sock.h> |
23 | #include <net/netfilter/nf_tproxy_core.h> | 22 | #include <net/netfilter/nf_tproxy_core.h> |
24 | #include <net/netfilter/ipv4/nf_defrag_ipv4.h> | 23 | #include <net/netfilter/ipv4/nf_defrag_ipv4.h> |
24 | |||
25 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | ||
26 | #define XT_SOCKET_HAVE_IPV6 1 | ||
27 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
25 | #include <net/netfilter/ipv6/nf_defrag_ipv6.h> | 28 | #include <net/netfilter/ipv6/nf_defrag_ipv6.h> |
29 | #endif | ||
26 | 30 | ||
27 | #include <linux/netfilter/xt_socket.h> | 31 | #include <linux/netfilter/xt_socket.h> |
28 | 32 | ||
@@ -186,7 +190,7 @@ socket_mt4_v1(const struct sk_buff *skb, struct xt_action_param *par) | |||
186 | return socket_match(skb, par, par->matchinfo); | 190 | return socket_match(skb, par, par->matchinfo); |
187 | } | 191 | } |
188 | 192 | ||
189 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 193 | #ifdef XT_SOCKET_HAVE_IPV6 |
190 | 194 | ||
191 | static int | 195 | static int |
192 | extract_icmp6_fields(const struct sk_buff *skb, | 196 | extract_icmp6_fields(const struct sk_buff *skb, |
@@ -331,7 +335,7 @@ static struct xt_match socket_mt_reg[] __read_mostly = { | |||
331 | (1 << NF_INET_LOCAL_IN), | 335 | (1 << NF_INET_LOCAL_IN), |
332 | .me = THIS_MODULE, | 336 | .me = THIS_MODULE, |
333 | }, | 337 | }, |
334 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 338 | #ifdef XT_SOCKET_HAVE_IPV6 |
335 | { | 339 | { |
336 | .name = "socket", | 340 | .name = "socket", |
337 | .revision = 1, | 341 | .revision = 1, |
@@ -348,7 +352,7 @@ static struct xt_match socket_mt_reg[] __read_mostly = { | |||
348 | static int __init socket_mt_init(void) | 352 | static int __init socket_mt_init(void) |
349 | { | 353 | { |
350 | nf_defrag_ipv4_enable(); | 354 | nf_defrag_ipv4_enable(); |
351 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 355 | #ifdef XT_SOCKET_HAVE_IPV6 |
352 | nf_defrag_ipv6_enable(); | 356 | nf_defrag_ipv6_enable(); |
353 | #endif | 357 | #endif |
354 | 358 | ||
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index cd96ed3ccee4..478181d53c55 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -83,9 +83,9 @@ struct netlink_sock { | |||
83 | struct module *module; | 83 | struct module *module; |
84 | }; | 84 | }; |
85 | 85 | ||
86 | struct listeners_rcu_head { | 86 | struct listeners { |
87 | struct rcu_head rcu_head; | 87 | struct rcu_head rcu; |
88 | void *ptr; | 88 | unsigned long masks[0]; |
89 | }; | 89 | }; |
90 | 90 | ||
91 | #define NETLINK_KERNEL_SOCKET 0x1 | 91 | #define NETLINK_KERNEL_SOCKET 0x1 |
@@ -119,7 +119,7 @@ struct nl_pid_hash { | |||
119 | struct netlink_table { | 119 | struct netlink_table { |
120 | struct nl_pid_hash hash; | 120 | struct nl_pid_hash hash; |
121 | struct hlist_head mc_list; | 121 | struct hlist_head mc_list; |
122 | unsigned long *listeners; | 122 | struct listeners __rcu *listeners; |
123 | unsigned int nl_nonroot; | 123 | unsigned int nl_nonroot; |
124 | unsigned int groups; | 124 | unsigned int groups; |
125 | struct mutex *cb_mutex; | 125 | struct mutex *cb_mutex; |
@@ -338,7 +338,7 @@ netlink_update_listeners(struct sock *sk) | |||
338 | if (i < NLGRPLONGS(nlk_sk(sk)->ngroups)) | 338 | if (i < NLGRPLONGS(nlk_sk(sk)->ngroups)) |
339 | mask |= nlk_sk(sk)->groups[i]; | 339 | mask |= nlk_sk(sk)->groups[i]; |
340 | } | 340 | } |
341 | tbl->listeners[i] = mask; | 341 | tbl->listeners->masks[i] = mask; |
342 | } | 342 | } |
343 | /* this function is only called with the netlink table "grabbed", which | 343 | /* this function is only called with the netlink table "grabbed", which |
344 | * makes sure updates are visible before bind or setsockopt return. */ | 344 | * makes sure updates are visible before bind or setsockopt return. */ |
@@ -936,7 +936,7 @@ EXPORT_SYMBOL(netlink_unicast); | |||
936 | int netlink_has_listeners(struct sock *sk, unsigned int group) | 936 | int netlink_has_listeners(struct sock *sk, unsigned int group) |
937 | { | 937 | { |
938 | int res = 0; | 938 | int res = 0; |
939 | unsigned long *listeners; | 939 | struct listeners *listeners; |
940 | 940 | ||
941 | BUG_ON(!netlink_is_kernel(sk)); | 941 | BUG_ON(!netlink_is_kernel(sk)); |
942 | 942 | ||
@@ -944,7 +944,7 @@ int netlink_has_listeners(struct sock *sk, unsigned int group) | |||
944 | listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners); | 944 | listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners); |
945 | 945 | ||
946 | if (group - 1 < nl_table[sk->sk_protocol].groups) | 946 | if (group - 1 < nl_table[sk->sk_protocol].groups) |
947 | res = test_bit(group - 1, listeners); | 947 | res = test_bit(group - 1, listeners->masks); |
948 | 948 | ||
949 | rcu_read_unlock(); | 949 | rcu_read_unlock(); |
950 | 950 | ||
@@ -1498,7 +1498,7 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups, | |||
1498 | struct socket *sock; | 1498 | struct socket *sock; |
1499 | struct sock *sk; | 1499 | struct sock *sk; |
1500 | struct netlink_sock *nlk; | 1500 | struct netlink_sock *nlk; |
1501 | unsigned long *listeners = NULL; | 1501 | struct listeners *listeners = NULL; |
1502 | 1502 | ||
1503 | BUG_ON(!nl_table); | 1503 | BUG_ON(!nl_table); |
1504 | 1504 | ||
@@ -1523,8 +1523,7 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups, | |||
1523 | if (groups < 32) | 1523 | if (groups < 32) |
1524 | groups = 32; | 1524 | groups = 32; |
1525 | 1525 | ||
1526 | listeners = kzalloc(NLGRPSZ(groups) + sizeof(struct listeners_rcu_head), | 1526 | listeners = kzalloc(sizeof(*listeners) + NLGRPSZ(groups), GFP_KERNEL); |
1527 | GFP_KERNEL); | ||
1528 | if (!listeners) | 1527 | if (!listeners) |
1529 | goto out_sock_release; | 1528 | goto out_sock_release; |
1530 | 1529 | ||
@@ -1541,7 +1540,7 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups, | |||
1541 | netlink_table_grab(); | 1540 | netlink_table_grab(); |
1542 | if (!nl_table[unit].registered) { | 1541 | if (!nl_table[unit].registered) { |
1543 | nl_table[unit].groups = groups; | 1542 | nl_table[unit].groups = groups; |
1544 | nl_table[unit].listeners = listeners; | 1543 | rcu_assign_pointer(nl_table[unit].listeners, listeners); |
1545 | nl_table[unit].cb_mutex = cb_mutex; | 1544 | nl_table[unit].cb_mutex = cb_mutex; |
1546 | nl_table[unit].module = module; | 1545 | nl_table[unit].module = module; |
1547 | nl_table[unit].registered = 1; | 1546 | nl_table[unit].registered = 1; |
@@ -1572,43 +1571,28 @@ netlink_kernel_release(struct sock *sk) | |||
1572 | EXPORT_SYMBOL(netlink_kernel_release); | 1571 | EXPORT_SYMBOL(netlink_kernel_release); |
1573 | 1572 | ||
1574 | 1573 | ||
1575 | static void netlink_free_old_listeners(struct rcu_head *rcu_head) | 1574 | static void listeners_free_rcu(struct rcu_head *head) |
1576 | { | 1575 | { |
1577 | struct listeners_rcu_head *lrh; | 1576 | kfree(container_of(head, struct listeners, rcu)); |
1578 | |||
1579 | lrh = container_of(rcu_head, struct listeners_rcu_head, rcu_head); | ||
1580 | kfree(lrh->ptr); | ||
1581 | } | 1577 | } |
1582 | 1578 | ||
1583 | int __netlink_change_ngroups(struct sock *sk, unsigned int groups) | 1579 | int __netlink_change_ngroups(struct sock *sk, unsigned int groups) |
1584 | { | 1580 | { |
1585 | unsigned long *listeners, *old = NULL; | 1581 | struct listeners *new, *old; |
1586 | struct listeners_rcu_head *old_rcu_head; | ||
1587 | struct netlink_table *tbl = &nl_table[sk->sk_protocol]; | 1582 | struct netlink_table *tbl = &nl_table[sk->sk_protocol]; |
1588 | 1583 | ||
1589 | if (groups < 32) | 1584 | if (groups < 32) |
1590 | groups = 32; | 1585 | groups = 32; |
1591 | 1586 | ||
1592 | if (NLGRPSZ(tbl->groups) < NLGRPSZ(groups)) { | 1587 | if (NLGRPSZ(tbl->groups) < NLGRPSZ(groups)) { |
1593 | listeners = kzalloc(NLGRPSZ(groups) + | 1588 | new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC); |
1594 | sizeof(struct listeners_rcu_head), | 1589 | if (!new) |
1595 | GFP_ATOMIC); | ||
1596 | if (!listeners) | ||
1597 | return -ENOMEM; | 1590 | return -ENOMEM; |
1598 | old = tbl->listeners; | 1591 | old = rcu_dereference_raw(tbl->listeners); |
1599 | memcpy(listeners, old, NLGRPSZ(tbl->groups)); | 1592 | memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups)); |
1600 | rcu_assign_pointer(tbl->listeners, listeners); | 1593 | rcu_assign_pointer(tbl->listeners, new); |
1601 | /* | 1594 | |
1602 | * Free the old memory after an RCU grace period so we | 1595 | call_rcu(&old->rcu, listeners_free_rcu); |
1603 | * don't leak it. We use call_rcu() here in order to be | ||
1604 | * able to call this function from atomic contexts. The | ||
1605 | * allocation of this memory will have reserved enough | ||
1606 | * space for struct listeners_rcu_head at the end. | ||
1607 | */ | ||
1608 | old_rcu_head = (void *)(tbl->listeners + | ||
1609 | NLGRPLONGS(tbl->groups)); | ||
1610 | old_rcu_head->ptr = old; | ||
1611 | call_rcu(&old_rcu_head->rcu_head, netlink_free_old_listeners); | ||
1612 | } | 1596 | } |
1613 | tbl->groups = groups; | 1597 | tbl->groups = groups; |
1614 | 1598 | ||
@@ -2104,18 +2088,17 @@ static void __net_exit netlink_net_exit(struct net *net) | |||
2104 | 2088 | ||
2105 | static void __init netlink_add_usersock_entry(void) | 2089 | static void __init netlink_add_usersock_entry(void) |
2106 | { | 2090 | { |
2107 | unsigned long *listeners; | 2091 | struct listeners *listeners; |
2108 | int groups = 32; | 2092 | int groups = 32; |
2109 | 2093 | ||
2110 | listeners = kzalloc(NLGRPSZ(groups) + sizeof(struct listeners_rcu_head), | 2094 | listeners = kzalloc(sizeof(*listeners) + NLGRPSZ(groups), GFP_KERNEL); |
2111 | GFP_KERNEL); | ||
2112 | if (!listeners) | 2095 | if (!listeners) |
2113 | panic("netlink_add_usersock_entry: Cannot allocate listneres\n"); | 2096 | panic("netlink_add_usersock_entry: Cannot allocate listeners\n"); |
2114 | 2097 | ||
2115 | netlink_table_grab(); | 2098 | netlink_table_grab(); |
2116 | 2099 | ||
2117 | nl_table[NETLINK_USERSOCK].groups = groups; | 2100 | nl_table[NETLINK_USERSOCK].groups = groups; |
2118 | nl_table[NETLINK_USERSOCK].listeners = listeners; | 2101 | rcu_assign_pointer(nl_table[NETLINK_USERSOCK].listeners, listeners); |
2119 | nl_table[NETLINK_USERSOCK].module = THIS_MODULE; | 2102 | nl_table[NETLINK_USERSOCK].module = THIS_MODULE; |
2120 | nl_table[NETLINK_USERSOCK].registered = 1; | 2103 | nl_table[NETLINK_USERSOCK].registered = 1; |
2121 | 2104 | ||