diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/core/dev.c | 4 | ||||
| -rw-r--r-- | net/core/fib_rules.c | 2 | ||||
| -rw-r--r-- | net/core/net_namespace.c | 28 | ||||
| -rw-r--r-- | net/core/sock.c | 19 | ||||
| -rw-r--r-- | net/decnet/dn_rules.c | 2 | ||||
| -rw-r--r-- | net/dsa/dsa.c | 23 | ||||
| -rw-r--r-- | net/ipv4/fib_frontend.c | 3 | ||||
| -rw-r--r-- | net/ipv4/ipmr.c | 5 | ||||
| -rw-r--r-- | net/ipv4/tcp_input.c | 7 | ||||
| -rw-r--r-- | net/ipv6/fib6_rules.c | 2 | ||||
| -rw-r--r-- | net/ipv6/ip6_output.c | 3 | ||||
| -rw-r--r-- | net/ipv6/ip6mr.c | 4 | ||||
| -rw-r--r-- | net/l2tp/l2tp_core.c | 1 |
13 files changed, 61 insertions, 42 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 962ee9d71964..45109b70664e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -2848,7 +2848,9 @@ static void skb_update_prio(struct sk_buff *skb) | |||
| 2848 | #define skb_update_prio(skb) | 2848 | #define skb_update_prio(skb) |
| 2849 | #endif | 2849 | #endif |
| 2850 | 2850 | ||
| 2851 | static DEFINE_PER_CPU(int, xmit_recursion); | 2851 | DEFINE_PER_CPU(int, xmit_recursion); |
| 2852 | EXPORT_SYMBOL(xmit_recursion); | ||
| 2853 | |||
| 2852 | #define RECURSION_LIMIT 10 | 2854 | #define RECURSION_LIMIT 10 |
| 2853 | 2855 | ||
| 2854 | /** | 2856 | /** |
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 44706e81b2e0..e4fdc9dfb2c7 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c | |||
| @@ -175,9 +175,9 @@ void fib_rules_unregister(struct fib_rules_ops *ops) | |||
| 175 | 175 | ||
| 176 | spin_lock(&net->rules_mod_lock); | 176 | spin_lock(&net->rules_mod_lock); |
| 177 | list_del_rcu(&ops->list); | 177 | list_del_rcu(&ops->list); |
| 178 | fib_rules_cleanup_ops(ops); | ||
| 179 | spin_unlock(&net->rules_mod_lock); | 178 | spin_unlock(&net->rules_mod_lock); |
| 180 | 179 | ||
| 180 | fib_rules_cleanup_ops(ops); | ||
| 181 | call_rcu(&ops->rcu, fib_rules_put_rcu); | 181 | call_rcu(&ops->rcu, fib_rules_put_rcu); |
| 182 | } | 182 | } |
| 183 | EXPORT_SYMBOL_GPL(fib_rules_unregister); | 183 | EXPORT_SYMBOL_GPL(fib_rules_unregister); |
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 5221f975a4cc..70d3450588b2 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
| @@ -198,8 +198,10 @@ static int __peernet2id(struct net *net, struct net *peer, bool alloc) | |||
| 198 | */ | 198 | */ |
| 199 | int peernet2id(struct net *net, struct net *peer) | 199 | int peernet2id(struct net *net, struct net *peer) |
| 200 | { | 200 | { |
| 201 | int id = __peernet2id(net, peer, true); | 201 | bool alloc = atomic_read(&peer->count) == 0 ? false : true; |
| 202 | int id; | ||
| 202 | 203 | ||
| 204 | id = __peernet2id(net, peer, alloc); | ||
| 203 | return id >= 0 ? id : NETNSA_NSID_NOT_ASSIGNED; | 205 | return id >= 0 ? id : NETNSA_NSID_NOT_ASSIGNED; |
| 204 | } | 206 | } |
| 205 | EXPORT_SYMBOL(peernet2id); | 207 | EXPORT_SYMBOL(peernet2id); |
| @@ -349,7 +351,7 @@ static LIST_HEAD(cleanup_list); /* Must hold cleanup_list_lock to touch */ | |||
| 349 | static void cleanup_net(struct work_struct *work) | 351 | static void cleanup_net(struct work_struct *work) |
| 350 | { | 352 | { |
| 351 | const struct pernet_operations *ops; | 353 | const struct pernet_operations *ops; |
| 352 | struct net *net, *tmp, *peer; | 354 | struct net *net, *tmp; |
| 353 | struct list_head net_kill_list; | 355 | struct list_head net_kill_list; |
| 354 | LIST_HEAD(net_exit_list); | 356 | LIST_HEAD(net_exit_list); |
| 355 | 357 | ||
| @@ -365,6 +367,14 @@ static void cleanup_net(struct work_struct *work) | |||
| 365 | list_for_each_entry(net, &net_kill_list, cleanup_list) { | 367 | list_for_each_entry(net, &net_kill_list, cleanup_list) { |
| 366 | list_del_rcu(&net->list); | 368 | list_del_rcu(&net->list); |
| 367 | list_add_tail(&net->exit_list, &net_exit_list); | 369 | list_add_tail(&net->exit_list, &net_exit_list); |
| 370 | for_each_net(tmp) { | ||
| 371 | int id = __peernet2id(tmp, net, false); | ||
| 372 | |||
| 373 | if (id >= 0) | ||
| 374 | idr_remove(&tmp->netns_ids, id); | ||
| 375 | } | ||
| 376 | idr_destroy(&net->netns_ids); | ||
| 377 | |||
| 368 | } | 378 | } |
| 369 | rtnl_unlock(); | 379 | rtnl_unlock(); |
| 370 | 380 | ||
| @@ -390,26 +400,12 @@ static void cleanup_net(struct work_struct *work) | |||
| 390 | */ | 400 | */ |
| 391 | rcu_barrier(); | 401 | rcu_barrier(); |
| 392 | 402 | ||
| 393 | rtnl_lock(); | ||
| 394 | /* Finally it is safe to free my network namespace structure */ | 403 | /* Finally it is safe to free my network namespace structure */ |
| 395 | list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { | 404 | list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { |
| 396 | /* Unreference net from all peers (no need to loop over | ||
| 397 | * net_exit_list because idr_destroy() will be called for each | ||
| 398 | * element of this list. | ||
| 399 | */ | ||
| 400 | for_each_net(peer) { | ||
| 401 | int id = __peernet2id(peer, net, false); | ||
| 402 | |||
| 403 | if (id >= 0) | ||
| 404 | idr_remove(&peer->netns_ids, id); | ||
| 405 | } | ||
| 406 | idr_destroy(&net->netns_ids); | ||
| 407 | |||
| 408 | list_del_init(&net->exit_list); | 405 | list_del_init(&net->exit_list); |
| 409 | put_user_ns(net->user_ns); | 406 | put_user_ns(net->user_ns); |
| 410 | net_drop_ns(net); | 407 | net_drop_ns(net); |
| 411 | } | 408 | } |
| 412 | rtnl_unlock(); | ||
| 413 | } | 409 | } |
| 414 | static DECLARE_WORK(net_cleanup_work, cleanup_net); | 410 | static DECLARE_WORK(net_cleanup_work, cleanup_net); |
| 415 | 411 | ||
diff --git a/net/core/sock.c b/net/core/sock.c index 78e89eb7eb70..71e3e5f1eaa0 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
| @@ -653,6 +653,25 @@ static inline void sock_valbool_flag(struct sock *sk, int bit, int valbool) | |||
| 653 | sock_reset_flag(sk, bit); | 653 | sock_reset_flag(sk, bit); |
| 654 | } | 654 | } |
| 655 | 655 | ||
| 656 | bool sk_mc_loop(struct sock *sk) | ||
| 657 | { | ||
| 658 | if (dev_recursion_level()) | ||
| 659 | return false; | ||
| 660 | if (!sk) | ||
| 661 | return true; | ||
| 662 | switch (sk->sk_family) { | ||
| 663 | case AF_INET: | ||
| 664 | return inet_sk(sk)->mc_loop; | ||
| 665 | #if IS_ENABLED(CONFIG_IPV6) | ||
| 666 | case AF_INET6: | ||
| 667 | return inet6_sk(sk)->mc_loop; | ||
| 668 | #endif | ||
| 669 | } | ||
| 670 | WARN_ON(1); | ||
| 671 | return true; | ||
| 672 | } | ||
| 673 | EXPORT_SYMBOL(sk_mc_loop); | ||
| 674 | |||
| 656 | /* | 675 | /* |
| 657 | * This is meant for all protocols to use and covers goings on | 676 | * This is meant for all protocols to use and covers goings on |
| 658 | * at the socket level. Everything here is generic. | 677 | * at the socket level. Everything here is generic. |
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index faf7cc3483fe..9d66a0f72f90 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c | |||
| @@ -248,7 +248,9 @@ void __init dn_fib_rules_init(void) | |||
| 248 | 248 | ||
| 249 | void __exit dn_fib_rules_cleanup(void) | 249 | void __exit dn_fib_rules_cleanup(void) |
| 250 | { | 250 | { |
| 251 | rtnl_lock(); | ||
| 251 | fib_rules_unregister(dn_fib_rules_ops); | 252 | fib_rules_unregister(dn_fib_rules_ops); |
| 253 | rtnl_unlock(); | ||
| 252 | rcu_barrier(); | 254 | rcu_barrier(); |
| 253 | } | 255 | } |
| 254 | 256 | ||
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 2173402d87e0..4dea2e0681d1 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c | |||
| @@ -501,12 +501,10 @@ static struct net_device *dev_to_net_device(struct device *dev) | |||
| 501 | #ifdef CONFIG_OF | 501 | #ifdef CONFIG_OF |
| 502 | static int dsa_of_setup_routing_table(struct dsa_platform_data *pd, | 502 | static int dsa_of_setup_routing_table(struct dsa_platform_data *pd, |
| 503 | struct dsa_chip_data *cd, | 503 | struct dsa_chip_data *cd, |
| 504 | int chip_index, | 504 | int chip_index, int port_index, |
| 505 | struct device_node *link) | 505 | struct device_node *link) |
| 506 | { | 506 | { |
| 507 | int ret; | ||
| 508 | const __be32 *reg; | 507 | const __be32 *reg; |
| 509 | int link_port_addr; | ||
| 510 | int link_sw_addr; | 508 | int link_sw_addr; |
| 511 | struct device_node *parent_sw; | 509 | struct device_node *parent_sw; |
| 512 | int len; | 510 | int len; |
| @@ -519,6 +517,10 @@ static int dsa_of_setup_routing_table(struct dsa_platform_data *pd, | |||
| 519 | if (!reg || (len != sizeof(*reg) * 2)) | 517 | if (!reg || (len != sizeof(*reg) * 2)) |
| 520 | return -EINVAL; | 518 | return -EINVAL; |
| 521 | 519 | ||
| 520 | /* | ||
| 521 | * Get the destination switch number from the second field of its 'reg' | ||
| 522 | * property, i.e. for "reg = <0x19 1>" sw_addr is '1'. | ||
| 523 | */ | ||
| 522 | link_sw_addr = be32_to_cpup(reg + 1); | 524 | link_sw_addr = be32_to_cpup(reg + 1); |
| 523 | 525 | ||
| 524 | if (link_sw_addr >= pd->nr_chips) | 526 | if (link_sw_addr >= pd->nr_chips) |
| @@ -535,20 +537,9 @@ static int dsa_of_setup_routing_table(struct dsa_platform_data *pd, | |||
| 535 | memset(cd->rtable, -1, pd->nr_chips * sizeof(s8)); | 537 | memset(cd->rtable, -1, pd->nr_chips * sizeof(s8)); |
| 536 | } | 538 | } |
| 537 | 539 | ||
| 538 | reg = of_get_property(link, "reg", NULL); | 540 | cd->rtable[link_sw_addr] = port_index; |
| 539 | if (!reg) { | ||
| 540 | ret = -EINVAL; | ||
| 541 | goto out; | ||
| 542 | } | ||
| 543 | |||
| 544 | link_port_addr = be32_to_cpup(reg); | ||
| 545 | |||
| 546 | cd->rtable[link_sw_addr] = link_port_addr; | ||
| 547 | 541 | ||
| 548 | return 0; | 542 | return 0; |
| 549 | out: | ||
| 550 | kfree(cd->rtable); | ||
| 551 | return ret; | ||
| 552 | } | 543 | } |
| 553 | 544 | ||
| 554 | static void dsa_of_free_platform_data(struct dsa_platform_data *pd) | 545 | static void dsa_of_free_platform_data(struct dsa_platform_data *pd) |
| @@ -658,7 +649,7 @@ static int dsa_of_probe(struct platform_device *pdev) | |||
| 658 | if (!strcmp(port_name, "dsa") && link && | 649 | if (!strcmp(port_name, "dsa") && link && |
| 659 | pd->nr_chips > 1) { | 650 | pd->nr_chips > 1) { |
| 660 | ret = dsa_of_setup_routing_table(pd, cd, | 651 | ret = dsa_of_setup_routing_table(pd, cd, |
| 661 | chip_index, link); | 652 | chip_index, port_index, link); |
| 662 | if (ret) | 653 | if (ret) |
| 663 | goto out_free_chip; | 654 | goto out_free_chip; |
| 664 | } | 655 | } |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 57be71dd6a9e..23b9b3e86f4c 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
| @@ -1111,11 +1111,10 @@ static void ip_fib_net_exit(struct net *net) | |||
| 1111 | { | 1111 | { |
| 1112 | unsigned int i; | 1112 | unsigned int i; |
| 1113 | 1113 | ||
| 1114 | rtnl_lock(); | ||
| 1114 | #ifdef CONFIG_IP_MULTIPLE_TABLES | 1115 | #ifdef CONFIG_IP_MULTIPLE_TABLES |
| 1115 | fib4_rules_exit(net); | 1116 | fib4_rules_exit(net); |
| 1116 | #endif | 1117 | #endif |
| 1117 | |||
| 1118 | rtnl_lock(); | ||
| 1119 | for (i = 0; i < FIB_TABLE_HASHSZ; i++) { | 1118 | for (i = 0; i < FIB_TABLE_HASHSZ; i++) { |
| 1120 | struct fib_table *tb; | 1119 | struct fib_table *tb; |
| 1121 | struct hlist_head *head; | 1120 | struct hlist_head *head; |
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 92825443fad6..fe54eba6d00d 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
| @@ -278,11 +278,13 @@ static void __net_exit ipmr_rules_exit(struct net *net) | |||
| 278 | { | 278 | { |
| 279 | struct mr_table *mrt, *next; | 279 | struct mr_table *mrt, *next; |
| 280 | 280 | ||
| 281 | rtnl_lock(); | ||
| 281 | list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) { | 282 | list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) { |
| 282 | list_del(&mrt->list); | 283 | list_del(&mrt->list); |
| 283 | ipmr_free_table(mrt); | 284 | ipmr_free_table(mrt); |
| 284 | } | 285 | } |
| 285 | fib_rules_unregister(net->ipv4.mr_rules_ops); | 286 | fib_rules_unregister(net->ipv4.mr_rules_ops); |
| 287 | rtnl_unlock(); | ||
| 286 | } | 288 | } |
| 287 | #else | 289 | #else |
| 288 | #define ipmr_for_each_table(mrt, net) \ | 290 | #define ipmr_for_each_table(mrt, net) \ |
| @@ -308,7 +310,10 @@ static int __net_init ipmr_rules_init(struct net *net) | |||
| 308 | 310 | ||
| 309 | static void __net_exit ipmr_rules_exit(struct net *net) | 311 | static void __net_exit ipmr_rules_exit(struct net *net) |
| 310 | { | 312 | { |
| 313 | rtnl_lock(); | ||
| 311 | ipmr_free_table(net->ipv4.mrt); | 314 | ipmr_free_table(net->ipv4.mrt); |
| 315 | net->ipv4.mrt = NULL; | ||
| 316 | rtnl_unlock(); | ||
| 312 | } | 317 | } |
| 313 | #endif | 318 | #endif |
| 314 | 319 | ||
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index fb4cf8b8e121..f501ac048366 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -3105,10 +3105,11 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, | |||
| 3105 | if (!first_ackt.v64) | 3105 | if (!first_ackt.v64) |
| 3106 | first_ackt = last_ackt; | 3106 | first_ackt = last_ackt; |
| 3107 | 3107 | ||
| 3108 | if (!(sacked & TCPCB_SACKED_ACKED)) | 3108 | if (!(sacked & TCPCB_SACKED_ACKED)) { |
| 3109 | reord = min(pkts_acked, reord); | 3109 | reord = min(pkts_acked, reord); |
| 3110 | if (!after(scb->end_seq, tp->high_seq)) | 3110 | if (!after(scb->end_seq, tp->high_seq)) |
| 3111 | flag |= FLAG_ORIG_SACK_ACKED; | 3111 | flag |= FLAG_ORIG_SACK_ACKED; |
| 3112 | } | ||
| 3112 | } | 3113 | } |
| 3113 | 3114 | ||
| 3114 | if (sacked & TCPCB_SACKED_ACKED) | 3115 | if (sacked & TCPCB_SACKED_ACKED) |
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 27ca79682efb..70bc6abc0639 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
| @@ -322,7 +322,9 @@ out_fib6_rules_ops: | |||
| 322 | 322 | ||
| 323 | static void __net_exit fib6_rules_net_exit(struct net *net) | 323 | static void __net_exit fib6_rules_net_exit(struct net *net) |
| 324 | { | 324 | { |
| 325 | rtnl_lock(); | ||
| 325 | fib_rules_unregister(net->ipv6.fib6_rules_ops); | 326 | fib_rules_unregister(net->ipv6.fib6_rules_ops); |
| 327 | rtnl_unlock(); | ||
| 326 | } | 328 | } |
| 327 | 329 | ||
| 328 | static struct pernet_operations fib6_rules_net_ops = { | 330 | static struct pernet_operations fib6_rules_net_ops = { |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 7e80b61b51ff..36cf0ab685a0 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -542,7 +542,8 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
| 542 | { | 542 | { |
| 543 | struct sk_buff *frag; | 543 | struct sk_buff *frag; |
| 544 | struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); | 544 | struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); |
| 545 | struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL; | 545 | struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ? |
| 546 | inet6_sk(skb->sk) : NULL; | ||
| 546 | struct ipv6hdr *tmp_hdr; | 547 | struct ipv6hdr *tmp_hdr; |
| 547 | struct frag_hdr *fh; | 548 | struct frag_hdr *fh; |
| 548 | unsigned int mtu, hlen, left, len; | 549 | unsigned int mtu, hlen, left, len; |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 52028f449a89..312e0ff47339 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
| @@ -267,8 +267,8 @@ static void __net_exit ip6mr_rules_exit(struct net *net) | |||
| 267 | list_del(&mrt->list); | 267 | list_del(&mrt->list); |
| 268 | ip6mr_free_table(mrt); | 268 | ip6mr_free_table(mrt); |
| 269 | } | 269 | } |
| 270 | rtnl_unlock(); | ||
| 271 | fib_rules_unregister(net->ipv6.mr6_rules_ops); | 270 | fib_rules_unregister(net->ipv6.mr6_rules_ops); |
| 271 | rtnl_unlock(); | ||
| 272 | } | 272 | } |
| 273 | #else | 273 | #else |
| 274 | #define ip6mr_for_each_table(mrt, net) \ | 274 | #define ip6mr_for_each_table(mrt, net) \ |
| @@ -336,7 +336,7 @@ static struct mr6_table *ip6mr_new_table(struct net *net, u32 id) | |||
| 336 | 336 | ||
| 337 | static void ip6mr_free_table(struct mr6_table *mrt) | 337 | static void ip6mr_free_table(struct mr6_table *mrt) |
| 338 | { | 338 | { |
| 339 | del_timer(&mrt->ipmr_expire_timer); | 339 | del_timer_sync(&mrt->ipmr_expire_timer); |
| 340 | mroute_clean_tables(mrt); | 340 | mroute_clean_tables(mrt); |
| 341 | kfree(mrt); | 341 | kfree(mrt); |
| 342 | } | 342 | } |
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 895348e44c7d..a29a504492af 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
| @@ -1871,6 +1871,7 @@ static int __init l2tp_init(void) | |||
| 1871 | l2tp_wq = alloc_workqueue("l2tp", WQ_UNBOUND, 0); | 1871 | l2tp_wq = alloc_workqueue("l2tp", WQ_UNBOUND, 0); |
| 1872 | if (!l2tp_wq) { | 1872 | if (!l2tp_wq) { |
| 1873 | pr_err("alloc_workqueue failed\n"); | 1873 | pr_err("alloc_workqueue failed\n"); |
| 1874 | unregister_pernet_device(&l2tp_net_ops); | ||
| 1874 | rc = -ENOMEM; | 1875 | rc = -ENOMEM; |
| 1875 | goto out; | 1876 | goto out; |
| 1876 | } | 1877 | } |
