From: Greg Kroah-Hartman Date: Tue, 29 Sep 2015 12:23:16 +0000 (+0200) Subject: 3.10-stable patches X-Git-Tag: v4.1.9~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b140bef125de8ca378837ab4178af37aa2cf06e3;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches added patches: fib_rules-fix-fib-rule-dumps-across-multiple-skbs.patch ip6_gre-release-cached-dst-on-tunnel-removal.patch ipv6-fix-exthdrs-offload-registration-in-out_rt-path.patch net-ipv6-correct-pim6-mrt_lock-handling.patch sctp-fix-race-on-protocol-netns-initialization.patch usbnet-get-event_no_runtime_pm-bit-before-it-is-cleared.patch --- diff --git a/queue-3.10/fib_rules-fix-fib-rule-dumps-across-multiple-skbs.patch b/queue-3.10/fib_rules-fix-fib-rule-dumps-across-multiple-skbs.patch new file mode 100644 index 00000000000..feb434b87e1 --- /dev/null +++ b/queue-3.10/fib_rules-fix-fib-rule-dumps-across-multiple-skbs.patch @@ -0,0 +1,72 @@ +From foo@baz Tue Sep 29 14:20:47 CEST 2015 +From: Wilson Kok +Date: Tue, 22 Sep 2015 21:40:22 -0700 +Subject: fib_rules: fix fib rule dumps across multiple skbs + +From: Wilson Kok + +[ Upstream commit 41fc014332d91ee90c32840bf161f9685b7fbf2b ] + +dump_rules returns skb length and not error. +But when family == AF_UNSPEC, the caller of dump_rules +assumes that it returns an error. Hence, when family == AF_UNSPEC, +we continue trying to dump on -EMSGSIZE errors resulting in +incorrect dump idx carried between skbs belonging to the same dump. +This results in fib rule dump always only dumping rules that fit +into the first skb. + +This patch fixes dump_rules to return error so that we exit correctly +and idx is correctly maintained between skbs that are part of the +same dump. + +Signed-off-by: Wilson Kok +Signed-off-by: Roopa Prabhu +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/fib_rules.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +--- a/net/core/fib_rules.c ++++ b/net/core/fib_rules.c +@@ -596,15 +596,17 @@ static int dump_rules(struct sk_buff *sk + { + int idx = 0; + struct fib_rule *rule; ++ int err = 0; + + rcu_read_lock(); + list_for_each_entry_rcu(rule, &ops->rules_list, list) { + if (idx < cb->args[1]) + goto skip; + +- if (fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).portid, +- cb->nlh->nlmsg_seq, RTM_NEWRULE, +- NLM_F_MULTI, ops) < 0) ++ err = fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).portid, ++ cb->nlh->nlmsg_seq, RTM_NEWRULE, ++ NLM_F_MULTI, ops); ++ if (err) + break; + skip: + idx++; +@@ -613,7 +615,7 @@ skip: + cb->args[1] = idx; + rules_ops_put(ops); + +- return skb->len; ++ return err; + } + + static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb) +@@ -629,7 +631,9 @@ static int fib_nl_dumprule(struct sk_buf + if (ops == NULL) + return -EAFNOSUPPORT; + +- return dump_rules(skb, cb, ops); ++ dump_rules(skb, cb, ops); ++ ++ return skb->len; + } + + rcu_read_lock(); diff --git a/queue-3.10/ip6_gre-release-cached-dst-on-tunnel-removal.patch b/queue-3.10/ip6_gre-release-cached-dst-on-tunnel-removal.patch new file mode 100644 index 00000000000..b83c1892145 --- /dev/null +++ b/queue-3.10/ip6_gre-release-cached-dst-on-tunnel-removal.patch @@ -0,0 +1,35 @@ +From foo@baz Tue Sep 29 14:20:47 CEST 2015 +From: huaibin Wang +Date: Tue, 25 Aug 2015 16:20:34 +0200 +Subject: ip6_gre: release cached dst on tunnel removal + +From: huaibin Wang + +[ Upstream commit d4257295ba1b389c693b79de857a96e4b7cd8ac0 ] + +When a tunnel is deleted, the cached dst entry should be released. + +This problem may prevent the removal of a netns (seen with a x-netns IPv6 +gre tunnel): + unregister_netdevice: waiting for lo to become free. Usage count = 3 + +CC: Dmitry Kozlov +Fixes: c12b395a4664 ("gre: Support GRE over IPv6") +Signed-off-by: huaibin Wang +Signed-off-by: Nicolas Dichtel +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/ip6_gre.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -359,6 +359,7 @@ static void ip6gre_tunnel_uninit(struct + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + + ip6gre_tunnel_unlink(ign, netdev_priv(dev)); ++ ip6_tnl_dst_reset(netdev_priv(dev)); + dev_put(dev); + } + diff --git a/queue-3.10/ipv6-fix-exthdrs-offload-registration-in-out_rt-path.patch b/queue-3.10/ipv6-fix-exthdrs-offload-registration-in-out_rt-path.patch new file mode 100644 index 00000000000..08c8ef56e91 --- /dev/null +++ b/queue-3.10/ipv6-fix-exthdrs-offload-registration-in-out_rt-path.patch @@ -0,0 +1,33 @@ +From foo@baz Tue Sep 29 14:20:47 CEST 2015 +From: Daniel Borkmann +Date: Thu, 3 Sep 2015 00:29:07 +0200 +Subject: ipv6: fix exthdrs offload registration in out_rt path + +From: Daniel Borkmann + +[ Upstream commit e41b0bedba0293b9e1e8d1e8ed553104b9693656 ] + +We previously register IPPROTO_ROUTING offload under inet6_add_offload(), +but in error path, we try to unregister it with inet_del_offload(). This +doesn't seem correct, it should actually be inet6_del_offload(), also +ipv6_exthdrs_offload_exit() from that commit seems rather incorrect (it +also uses rthdr_offload twice), but it got removed entirely later on. + +Fixes: 3336288a9fea ("ipv6: Switch to using new offload infrastructure.") +Signed-off-by: Daniel Borkmann +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/exthdrs_offload.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ipv6/exthdrs_offload.c ++++ b/net/ipv6/exthdrs_offload.c +@@ -36,6 +36,6 @@ out: + return ret; + + out_rt: +- inet_del_offload(&rthdr_offload, IPPROTO_ROUTING); ++ inet6_del_offload(&rthdr_offload, IPPROTO_ROUTING); + goto out; + } diff --git a/queue-3.10/net-ipv6-correct-pim6-mrt_lock-handling.patch b/queue-3.10/net-ipv6-correct-pim6-mrt_lock-handling.patch new file mode 100644 index 00000000000..ba2ce951278 --- /dev/null +++ b/queue-3.10/net-ipv6-correct-pim6-mrt_lock-handling.patch @@ -0,0 +1,35 @@ +From foo@baz Tue Sep 29 14:20:47 CEST 2015 +From: Richard Laing +Date: Thu, 3 Sep 2015 13:52:31 +1200 +Subject: net/ipv6: Correct PIM6 mrt_lock handling + +From: Richard Laing + +[ Upstream commit 25b4a44c19c83d98e8c0807a7ede07c1f28eab8b ] + +In the IPv6 multicast routing code the mrt_lock was not being released +correctly in the MFC iterator, as a result adding or deleting a MIF would +cause a hang because the mrt_lock could not be acquired. + +This fix is a copy of the code for the IPv4 case and ensures that the lock +is released correctly. + +Signed-off-by: Richard Laing +Acked-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/ip6mr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ipv6/ip6mr.c ++++ b/net/ipv6/ip6mr.c +@@ -552,7 +552,7 @@ static void ipmr_mfc_seq_stop(struct seq + + if (it->cache == &mrt->mfc6_unres_queue) + spin_unlock_bh(&mfc_unres_lock); +- else if (it->cache == mrt->mfc6_cache_array) ++ else if (it->cache == &mrt->mfc6_cache_array[it->ct]) + read_unlock(&mrt_lock); + } + diff --git a/queue-3.10/sctp-fix-race-on-protocol-netns-initialization.patch b/queue-3.10/sctp-fix-race-on-protocol-netns-initialization.patch new file mode 100644 index 00000000000..cb39c73f3ac --- /dev/null +++ b/queue-3.10/sctp-fix-race-on-protocol-netns-initialization.patch @@ -0,0 +1,232 @@ +From foo@baz Tue Sep 29 14:20:47 CEST 2015 +From: Marcelo Ricardo Leitner +Date: Thu, 10 Sep 2015 17:31:15 -0300 +Subject: sctp: fix race on protocol/netns initialization + +From: Marcelo Ricardo Leitner + +[ Upstream commit 8e2d61e0aed2b7c4ecb35844fe07e0b2b762dee4 ] + +Consider sctp module is unloaded and is being requested because an user +is creating a sctp socket. + +During initialization, sctp will add the new protocol type and then +initialize pernet subsys: + + status = sctp_v4_protosw_init(); + if (status) + goto err_protosw_init; + + status = sctp_v6_protosw_init(); + if (status) + goto err_v6_protosw_init; + + status = register_pernet_subsys(&sctp_net_ops); + +The problem is that after those calls to sctp_v{4,6}_protosw_init(), it +is possible for userspace to create SCTP sockets like if the module is +already fully loaded. If that happens, one of the possible effects is +that we will have readers for net->sctp.local_addr_list list earlier +than expected and sctp_net_init() does not take precautions while +dealing with that list, leading to a potential panic but not limited to +that, as sctp_sock_init() will copy a bunch of blank/partially +initialized values from net->sctp. + +The race happens like this: + + CPU 0 | CPU 1 + socket() | + __sock_create | socket() + inet_create | __sock_create + list_for_each_entry_rcu( | + answer, &inetsw[sock->type], | + list) { | inet_create + /* no hits */ | + if (unlikely(err)) { | + ... | + request_module() | + /* socket creation is blocked | + * the module is fully loaded | + */ | + sctp_init | + sctp_v4_protosw_init | + inet_register_protosw | + list_add_rcu(&p->list, | + last_perm); | + | list_for_each_entry_rcu( + | answer, &inetsw[sock->type], + sctp_v6_protosw_init | list) { + | /* hit, so assumes protocol + | * is already loaded + | */ + | /* socket creation continues + | * before netns is initialized + | */ + register_pernet_subsys | + +Simply inverting the initialization order between +register_pernet_subsys() and sctp_v4_protosw_init() is not possible +because register_pernet_subsys() will create a control sctp socket, so +the protocol must be already visible by then. Deferring the socket +creation to a work-queue is not good specially because we loose the +ability to handle its errors. + +So, as suggested by Vlad, the fix is to split netns initialization in +two moments: defaults and control socket, so that the defaults are +already loaded by when we register the protocol, while control socket +initialization is kept at the same moment it is today. + +Fixes: 4db67e808640 ("sctp: Make the address lists per network namespace") +Signed-off-by: Vlad Yasevich +Signed-off-by: Marcelo Ricardo Leitner +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/protocol.c | 64 +++++++++++++++++++++++++++++++++------------------- + 1 file changed, 41 insertions(+), 23 deletions(-) + +--- a/net/sctp/protocol.c ++++ b/net/sctp/protocol.c +@@ -1170,7 +1170,7 @@ static void sctp_v4_del_protocol(void) + unregister_inetaddr_notifier(&sctp_inetaddr_notifier); + } + +-static int __net_init sctp_net_init(struct net *net) ++static int __net_init sctp_defaults_init(struct net *net) + { + int status; + +@@ -1263,12 +1263,6 @@ static int __net_init sctp_net_init(stru + + sctp_dbg_objcnt_init(net); + +- /* Initialize the control inode/socket for handling OOTB packets. */ +- if ((status = sctp_ctl_sock_init(net))) { +- pr_err("Failed to initialize the SCTP control sock\n"); +- goto err_ctl_sock_init; +- } +- + /* Initialize the local address list. */ + INIT_LIST_HEAD(&net->sctp.local_addr_list); + spin_lock_init(&net->sctp.local_addr_lock); +@@ -1284,9 +1278,6 @@ static int __net_init sctp_net_init(stru + + return 0; + +-err_ctl_sock_init: +- sctp_dbg_objcnt_exit(net); +- sctp_proc_exit(net); + err_init_proc: + cleanup_sctp_mibs(net); + err_init_mibs: +@@ -1295,15 +1286,12 @@ err_sysctl_register: + return status; + } + +-static void __net_exit sctp_net_exit(struct net *net) ++static void __net_exit sctp_defaults_exit(struct net *net) + { + /* Free the local address list */ + sctp_free_addr_wq(net); + sctp_free_local_addr_list(net); + +- /* Free the control endpoint. */ +- inet_ctl_sock_destroy(net->sctp.ctl_sock); +- + sctp_dbg_objcnt_exit(net); + + sctp_proc_exit(net); +@@ -1311,9 +1299,32 @@ static void __net_exit sctp_net_exit(str + sctp_sysctl_net_unregister(net); + } + +-static struct pernet_operations sctp_net_ops = { +- .init = sctp_net_init, +- .exit = sctp_net_exit, ++static struct pernet_operations sctp_defaults_ops = { ++ .init = sctp_defaults_init, ++ .exit = sctp_defaults_exit, ++}; ++ ++static int __net_init sctp_ctrlsock_init(struct net *net) ++{ ++ int status; ++ ++ /* Initialize the control inode/socket for handling OOTB packets. */ ++ status = sctp_ctl_sock_init(net); ++ if (status) ++ pr_err("Failed to initialize the SCTP control sock\n"); ++ ++ return status; ++} ++ ++static void __net_init sctp_ctrlsock_exit(struct net *net) ++{ ++ /* Free the control endpoint. */ ++ inet_ctl_sock_destroy(net->sctp.ctl_sock); ++} ++ ++static struct pernet_operations sctp_ctrlsock_ops = { ++ .init = sctp_ctrlsock_init, ++ .exit = sctp_ctrlsock_exit, + }; + + /* Initialize the universe into something sensible. */ +@@ -1448,8 +1459,11 @@ SCTP_STATIC __init int sctp_init(void) + sctp_v4_pf_init(); + sctp_v6_pf_init(); + +- status = sctp_v4_protosw_init(); ++ status = register_pernet_subsys(&sctp_defaults_ops); ++ if (status) ++ goto err_register_defaults; + ++ status = sctp_v4_protosw_init(); + if (status) + goto err_protosw_init; + +@@ -1457,9 +1471,9 @@ SCTP_STATIC __init int sctp_init(void) + if (status) + goto err_v6_protosw_init; + +- status = register_pernet_subsys(&sctp_net_ops); ++ status = register_pernet_subsys(&sctp_ctrlsock_ops); + if (status) +- goto err_register_pernet_subsys; ++ goto err_register_ctrlsock; + + status = sctp_v4_add_protocol(); + if (status) +@@ -1476,12 +1490,14 @@ out: + err_v6_add_protocol: + sctp_v4_del_protocol(); + err_add_protocol: +- unregister_pernet_subsys(&sctp_net_ops); +-err_register_pernet_subsys: ++ unregister_pernet_subsys(&sctp_ctrlsock_ops); ++err_register_ctrlsock: + sctp_v6_protosw_exit(); + err_v6_protosw_init: + sctp_v4_protosw_exit(); + err_protosw_init: ++ unregister_pernet_subsys(&sctp_defaults_ops); ++err_register_defaults: + sctp_v4_pf_exit(); + sctp_v6_pf_exit(); + sctp_sysctl_unregister(); +@@ -1514,12 +1530,14 @@ SCTP_STATIC __exit void sctp_exit(void) + sctp_v6_del_protocol(); + sctp_v4_del_protocol(); + +- unregister_pernet_subsys(&sctp_net_ops); ++ unregister_pernet_subsys(&sctp_ctrlsock_ops); + + /* Free protosw registrations */ + sctp_v6_protosw_exit(); + sctp_v4_protosw_exit(); + ++ unregister_pernet_subsys(&sctp_defaults_ops); ++ + /* Unregister with socket layer. */ + sctp_v6_pf_exit(); + sctp_v4_pf_exit(); diff --git a/queue-3.10/series b/queue-3.10/series index 1839068d6fa..9bc6579494f 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -46,3 +46,9 @@ bonding-fix-destruction-of-bond-with-devices-different-from-arphrd_ether.patch inet-frags-fix-defragmented-packet-s-ip-header-for-af_packet.patch netlink-don-t-hold-mutex-in-rcu-callback-when-releasing-mmapd-ring.patch rds-fix-an-integer-overflow-test-in-rds_info_getsockopt.patch +ip6_gre-release-cached-dst-on-tunnel-removal.patch +usbnet-get-event_no_runtime_pm-bit-before-it-is-cleared.patch +ipv6-fix-exthdrs-offload-registration-in-out_rt-path.patch +net-ipv6-correct-pim6-mrt_lock-handling.patch +sctp-fix-race-on-protocol-netns-initialization.patch +fib_rules-fix-fib-rule-dumps-across-multiple-skbs.patch diff --git a/queue-3.10/usbnet-get-event_no_runtime_pm-bit-before-it-is-cleared.patch b/queue-3.10/usbnet-get-event_no_runtime_pm-bit-before-it-is-cleared.patch new file mode 100644 index 00000000000..88fc9c65402 --- /dev/null +++ b/queue-3.10/usbnet-get-event_no_runtime_pm-bit-before-it-is-cleared.patch @@ -0,0 +1,54 @@ +From foo@baz Tue Sep 29 14:20:47 CEST 2015 +From: Eugene Shatokhin +Date: Mon, 24 Aug 2015 23:13:42 +0300 +Subject: usbnet: Get EVENT_NO_RUNTIME_PM bit before it is cleared + +From: Eugene Shatokhin + +[ Upstream commit f50791ac1aca1ac1b0370d62397b43e9f831421a ] + +It is needed to check EVENT_NO_RUNTIME_PM bit of dev->flags in +usbnet_stop(), but its value should be read before it is cleared +when dev->flags is set to 0. + +The problem was spotted and the fix was provided by +Oliver Neukum . + +Signed-off-by: Eugene Shatokhin +Acked-by: Oliver Neukum +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/usbnet.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/net/usb/usbnet.c ++++ b/drivers/net/usb/usbnet.c +@@ -753,7 +753,7 @@ int usbnet_stop (struct net_device *net) + { + struct usbnet *dev = netdev_priv(net); + struct driver_info *info = dev->driver_info; +- int retval, pm; ++ int retval, pm, mpn; + + clear_bit(EVENT_DEV_OPEN, &dev->flags); + netif_stop_queue (net); +@@ -784,6 +784,8 @@ int usbnet_stop (struct net_device *net) + + usbnet_purge_paused_rxq(dev); + ++ mpn = !test_and_clear_bit(EVENT_NO_RUNTIME_PM, &dev->flags); ++ + /* deferred work (task, timer, softirq) must also stop. + * can't flush_scheduled_work() until we drop rtnl (later), + * else workers could deadlock; so make workers a NOP. +@@ -794,8 +796,7 @@ int usbnet_stop (struct net_device *net) + if (!pm) + usb_autopm_put_interface(dev->intf); + +- if (info->manage_power && +- !test_and_clear_bit(EVENT_NO_RUNTIME_PM, &dev->flags)) ++ if (info->manage_power && mpn) + info->manage_power(dev, 0); + else + usb_autopm_put_interface(dev->intf);