diff options
| author | Mark Brown <broonie@linaro.org> | 2013-10-07 06:46:56 -0400 |
|---|---|---|
| committer | Mark Brown <broonie@linaro.org> | 2013-10-07 06:46:56 -0400 |
| commit | 9f9e4266a66b6f9dcde305e85035615c06bdb7f7 (patch) | |
| tree | c6f867c7a1bf94a3b4f13b19a9ce442c7aec9e79 /net/core | |
| parent | bf551413038f74343ec4d1413c3610e2362d0aeb (diff) | |
| parent | 249ce1387b7739dbea2ac1a697e4bf1e37ec06b7 (diff) | |
Merge remote-tracking branch 'asoc/topic/dapm' into asoc-twl6040
Diffstat (limited to 'net/core')
| -rw-r--r-- | net/core/dev.c | 49 | ||||
| -rw-r--r-- | net/core/flow_dissector.c | 4 | ||||
| -rw-r--r-- | net/core/netpoll.c | 11 | ||||
| -rw-r--r-- | net/core/secure_seq.c | 27 |
4 files changed, 79 insertions, 12 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 5c713f2239cc..65f829cfd928 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -5247,10 +5247,12 @@ static int dev_new_index(struct net *net) | |||
| 5247 | 5247 | ||
| 5248 | /* Delayed registration/unregisteration */ | 5248 | /* Delayed registration/unregisteration */ |
| 5249 | static LIST_HEAD(net_todo_list); | 5249 | static LIST_HEAD(net_todo_list); |
| 5250 | static DECLARE_WAIT_QUEUE_HEAD(netdev_unregistering_wq); | ||
| 5250 | 5251 | ||
| 5251 | static void net_set_todo(struct net_device *dev) | 5252 | static void net_set_todo(struct net_device *dev) |
| 5252 | { | 5253 | { |
| 5253 | list_add_tail(&dev->todo_list, &net_todo_list); | 5254 | list_add_tail(&dev->todo_list, &net_todo_list); |
| 5255 | dev_net(dev)->dev_unreg_count++; | ||
| 5254 | } | 5256 | } |
| 5255 | 5257 | ||
| 5256 | static void rollback_registered_many(struct list_head *head) | 5258 | static void rollback_registered_many(struct list_head *head) |
| @@ -5918,6 +5920,12 @@ void netdev_run_todo(void) | |||
| 5918 | if (dev->destructor) | 5920 | if (dev->destructor) |
| 5919 | dev->destructor(dev); | 5921 | dev->destructor(dev); |
| 5920 | 5922 | ||
| 5923 | /* Report a network device has been unregistered */ | ||
| 5924 | rtnl_lock(); | ||
| 5925 | dev_net(dev)->dev_unreg_count--; | ||
| 5926 | __rtnl_unlock(); | ||
| 5927 | wake_up(&netdev_unregistering_wq); | ||
| 5928 | |||
| 5921 | /* Free network device */ | 5929 | /* Free network device */ |
| 5922 | kobject_put(&dev->dev.kobj); | 5930 | kobject_put(&dev->dev.kobj); |
| 5923 | } | 5931 | } |
| @@ -6603,6 +6611,34 @@ static void __net_exit default_device_exit(struct net *net) | |||
| 6603 | rtnl_unlock(); | 6611 | rtnl_unlock(); |
| 6604 | } | 6612 | } |
| 6605 | 6613 | ||
| 6614 | static void __net_exit rtnl_lock_unregistering(struct list_head *net_list) | ||
| 6615 | { | ||
| 6616 | /* Return with the rtnl_lock held when there are no network | ||
| 6617 | * devices unregistering in any network namespace in net_list. | ||
| 6618 | */ | ||
| 6619 | struct net *net; | ||
| 6620 | bool unregistering; | ||
| 6621 | DEFINE_WAIT(wait); | ||
| 6622 | |||
| 6623 | for (;;) { | ||
| 6624 | prepare_to_wait(&netdev_unregistering_wq, &wait, | ||
| 6625 | TASK_UNINTERRUPTIBLE); | ||
| 6626 | unregistering = false; | ||
| 6627 | rtnl_lock(); | ||
| 6628 | list_for_each_entry(net, net_list, exit_list) { | ||
| 6629 | if (net->dev_unreg_count > 0) { | ||
| 6630 | unregistering = true; | ||
| 6631 | break; | ||
| 6632 | } | ||
| 6633 | } | ||
| 6634 | if (!unregistering) | ||
| 6635 | break; | ||
| 6636 | __rtnl_unlock(); | ||
| 6637 | schedule(); | ||
| 6638 | } | ||
| 6639 | finish_wait(&netdev_unregistering_wq, &wait); | ||
| 6640 | } | ||
| 6641 | |||
| 6606 | static void __net_exit default_device_exit_batch(struct list_head *net_list) | 6642 | static void __net_exit default_device_exit_batch(struct list_head *net_list) |
| 6607 | { | 6643 | { |
| 6608 | /* At exit all network devices most be removed from a network | 6644 | /* At exit all network devices most be removed from a network |
| @@ -6614,7 +6650,18 @@ static void __net_exit default_device_exit_batch(struct list_head *net_list) | |||
| 6614 | struct net *net; | 6650 | struct net *net; |
| 6615 | LIST_HEAD(dev_kill_list); | 6651 | LIST_HEAD(dev_kill_list); |
| 6616 | 6652 | ||
| 6617 | rtnl_lock(); | 6653 | /* To prevent network device cleanup code from dereferencing |
| 6654 | * loopback devices or network devices that have been freed | ||
| 6655 | * wait here for all pending unregistrations to complete, | ||
| 6656 | * before unregistring the loopback device and allowing the | ||
| 6657 | * network namespace be freed. | ||
| 6658 | * | ||
| 6659 | * The netdev todo list containing all network devices | ||
| 6660 | * unregistrations that happen in default_device_exit_batch | ||
| 6661 | * will run in the rtnl_unlock() at the end of | ||
| 6662 | * default_device_exit_batch. | ||
| 6663 | */ | ||
| 6664 | rtnl_lock_unregistering(net_list); | ||
| 6618 | list_for_each_entry(net, net_list, exit_list) { | 6665 | list_for_each_entry(net, net_list, exit_list) { |
| 6619 | for_each_netdev_reverse(net, dev) { | 6666 | for_each_netdev_reverse(net, dev) { |
| 6620 | if (dev->rtnl_link_ops) | 6667 | if (dev->rtnl_link_ops) |
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 1929af87b260..8d7d0dd72db2 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c | |||
| @@ -154,8 +154,8 @@ ipv6: | |||
| 154 | if (poff >= 0) { | 154 | if (poff >= 0) { |
| 155 | __be32 *ports, _ports; | 155 | __be32 *ports, _ports; |
| 156 | 156 | ||
| 157 | nhoff += poff; | 157 | ports = skb_header_pointer(skb, nhoff + poff, |
| 158 | ports = skb_header_pointer(skb, nhoff, sizeof(_ports), &_ports); | 158 | sizeof(_ports), &_ports); |
| 159 | if (ports) | 159 | if (ports) |
| 160 | flow->ports = *ports; | 160 | flow->ports = *ports; |
| 161 | } | 161 | } |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 2c637e9a0b27..fc75c9e461b8 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
| @@ -550,7 +550,7 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo | |||
| 550 | return; | 550 | return; |
| 551 | 551 | ||
| 552 | proto = ntohs(eth_hdr(skb)->h_proto); | 552 | proto = ntohs(eth_hdr(skb)->h_proto); |
| 553 | if (proto == ETH_P_IP) { | 553 | if (proto == ETH_P_ARP) { |
| 554 | struct arphdr *arp; | 554 | struct arphdr *arp; |
| 555 | unsigned char *arp_ptr; | 555 | unsigned char *arp_ptr; |
| 556 | /* No arp on this interface */ | 556 | /* No arp on this interface */ |
| @@ -1284,15 +1284,14 @@ EXPORT_SYMBOL_GPL(__netpoll_free_async); | |||
| 1284 | 1284 | ||
| 1285 | void netpoll_cleanup(struct netpoll *np) | 1285 | void netpoll_cleanup(struct netpoll *np) |
| 1286 | { | 1286 | { |
| 1287 | if (!np->dev) | ||
| 1288 | return; | ||
| 1289 | |||
| 1290 | rtnl_lock(); | 1287 | rtnl_lock(); |
| 1288 | if (!np->dev) | ||
| 1289 | goto out; | ||
| 1291 | __netpoll_cleanup(np); | 1290 | __netpoll_cleanup(np); |
| 1292 | rtnl_unlock(); | ||
| 1293 | |||
| 1294 | dev_put(np->dev); | 1291 | dev_put(np->dev); |
| 1295 | np->dev = NULL; | 1292 | np->dev = NULL; |
| 1293 | out: | ||
| 1294 | rtnl_unlock(); | ||
| 1296 | } | 1295 | } |
| 1297 | EXPORT_SYMBOL(netpoll_cleanup); | 1296 | EXPORT_SYMBOL(netpoll_cleanup); |
| 1298 | 1297 | ||
diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c index 6a2f13cee86a..3f1ec1586ae1 100644 --- a/net/core/secure_seq.c +++ b/net/core/secure_seq.c | |||
| @@ -10,11 +10,24 @@ | |||
| 10 | 10 | ||
| 11 | #include <net/secure_seq.h> | 11 | #include <net/secure_seq.h> |
| 12 | 12 | ||
| 13 | static u32 net_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned; | 13 | #define NET_SECRET_SIZE (MD5_MESSAGE_BYTES / 4) |
| 14 | 14 | ||
| 15 | void net_secret_init(void) | 15 | static u32 net_secret[NET_SECRET_SIZE] ____cacheline_aligned; |
| 16 | |||
| 17 | static void net_secret_init(void) | ||
| 16 | { | 18 | { |
| 17 | get_random_bytes(net_secret, sizeof(net_secret)); | 19 | u32 tmp; |
| 20 | int i; | ||
| 21 | |||
| 22 | if (likely(net_secret[0])) | ||
| 23 | return; | ||
| 24 | |||
| 25 | for (i = NET_SECRET_SIZE; i > 0;) { | ||
| 26 | do { | ||
| 27 | get_random_bytes(&tmp, sizeof(tmp)); | ||
| 28 | } while (!tmp); | ||
| 29 | cmpxchg(&net_secret[--i], 0, tmp); | ||
| 30 | } | ||
| 18 | } | 31 | } |
| 19 | 32 | ||
| 20 | #ifdef CONFIG_INET | 33 | #ifdef CONFIG_INET |
| @@ -42,6 +55,7 @@ __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr, | |||
| 42 | u32 hash[MD5_DIGEST_WORDS]; | 55 | u32 hash[MD5_DIGEST_WORDS]; |
| 43 | u32 i; | 56 | u32 i; |
| 44 | 57 | ||
| 58 | net_secret_init(); | ||
| 45 | memcpy(hash, saddr, 16); | 59 | memcpy(hash, saddr, 16); |
| 46 | for (i = 0; i < 4; i++) | 60 | for (i = 0; i < 4; i++) |
| 47 | secret[i] = net_secret[i] + (__force u32)daddr[i]; | 61 | secret[i] = net_secret[i] + (__force u32)daddr[i]; |
| @@ -63,6 +77,7 @@ u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, | |||
| 63 | u32 hash[MD5_DIGEST_WORDS]; | 77 | u32 hash[MD5_DIGEST_WORDS]; |
| 64 | u32 i; | 78 | u32 i; |
| 65 | 79 | ||
| 80 | net_secret_init(); | ||
| 66 | memcpy(hash, saddr, 16); | 81 | memcpy(hash, saddr, 16); |
| 67 | for (i = 0; i < 4; i++) | 82 | for (i = 0; i < 4; i++) |
| 68 | secret[i] = net_secret[i] + (__force u32) daddr[i]; | 83 | secret[i] = net_secret[i] + (__force u32) daddr[i]; |
| @@ -82,6 +97,7 @@ __u32 secure_ip_id(__be32 daddr) | |||
| 82 | { | 97 | { |
| 83 | u32 hash[MD5_DIGEST_WORDS]; | 98 | u32 hash[MD5_DIGEST_WORDS]; |
| 84 | 99 | ||
| 100 | net_secret_init(); | ||
| 85 | hash[0] = (__force __u32) daddr; | 101 | hash[0] = (__force __u32) daddr; |
| 86 | hash[1] = net_secret[13]; | 102 | hash[1] = net_secret[13]; |
| 87 | hash[2] = net_secret[14]; | 103 | hash[2] = net_secret[14]; |
| @@ -96,6 +112,7 @@ __u32 secure_ipv6_id(const __be32 daddr[4]) | |||
| 96 | { | 112 | { |
| 97 | __u32 hash[4]; | 113 | __u32 hash[4]; |
| 98 | 114 | ||
| 115 | net_secret_init(); | ||
| 99 | memcpy(hash, daddr, 16); | 116 | memcpy(hash, daddr, 16); |
| 100 | md5_transform(hash, net_secret); | 117 | md5_transform(hash, net_secret); |
| 101 | 118 | ||
| @@ -107,6 +124,7 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, | |||
| 107 | { | 124 | { |
| 108 | u32 hash[MD5_DIGEST_WORDS]; | 125 | u32 hash[MD5_DIGEST_WORDS]; |
| 109 | 126 | ||
| 127 | net_secret_init(); | ||
| 110 | hash[0] = (__force u32)saddr; | 128 | hash[0] = (__force u32)saddr; |
| 111 | hash[1] = (__force u32)daddr; | 129 | hash[1] = (__force u32)daddr; |
| 112 | hash[2] = ((__force u16)sport << 16) + (__force u16)dport; | 130 | hash[2] = ((__force u16)sport << 16) + (__force u16)dport; |
| @@ -121,6 +139,7 @@ u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport) | |||
| 121 | { | 139 | { |
| 122 | u32 hash[MD5_DIGEST_WORDS]; | 140 | u32 hash[MD5_DIGEST_WORDS]; |
| 123 | 141 | ||
| 142 | net_secret_init(); | ||
| 124 | hash[0] = (__force u32)saddr; | 143 | hash[0] = (__force u32)saddr; |
| 125 | hash[1] = (__force u32)daddr; | 144 | hash[1] = (__force u32)daddr; |
| 126 | hash[2] = (__force u32)dport ^ net_secret[14]; | 145 | hash[2] = (__force u32)dport ^ net_secret[14]; |
| @@ -140,6 +159,7 @@ u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, | |||
| 140 | u32 hash[MD5_DIGEST_WORDS]; | 159 | u32 hash[MD5_DIGEST_WORDS]; |
| 141 | u64 seq; | 160 | u64 seq; |
| 142 | 161 | ||
| 162 | net_secret_init(); | ||
| 143 | hash[0] = (__force u32)saddr; | 163 | hash[0] = (__force u32)saddr; |
| 144 | hash[1] = (__force u32)daddr; | 164 | hash[1] = (__force u32)daddr; |
| 145 | hash[2] = ((__force u16)sport << 16) + (__force u16)dport; | 165 | hash[2] = ((__force u16)sport << 16) + (__force u16)dport; |
| @@ -164,6 +184,7 @@ u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr, | |||
| 164 | u64 seq; | 184 | u64 seq; |
| 165 | u32 i; | 185 | u32 i; |
| 166 | 186 | ||
| 187 | net_secret_init(); | ||
| 167 | memcpy(hash, saddr, 16); | 188 | memcpy(hash, saddr, 16); |
| 168 | for (i = 0; i < 4; i++) | 189 | for (i = 0; i < 4; i++) |
| 169 | secret[i] = net_secret[i] + daddr[i]; | 190 | secret[i] = net_secret[i] + daddr[i]; |
