]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 29 Sep 2015 12:23:16 +0000 (14:23 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 29 Sep 2015 12:23:16 +0000 (14:23 +0200)
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

queue-3.10/fib_rules-fix-fib-rule-dumps-across-multiple-skbs.patch [new file with mode: 0644]
queue-3.10/ip6_gre-release-cached-dst-on-tunnel-removal.patch [new file with mode: 0644]
queue-3.10/ipv6-fix-exthdrs-offload-registration-in-out_rt-path.patch [new file with mode: 0644]
queue-3.10/net-ipv6-correct-pim6-mrt_lock-handling.patch [new file with mode: 0644]
queue-3.10/sctp-fix-race-on-protocol-netns-initialization.patch [new file with mode: 0644]
queue-3.10/series
queue-3.10/usbnet-get-event_no_runtime_pm-bit-before-it-is-cleared.patch [new file with mode: 0644]

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 (file)
index 0000000..feb434b
--- /dev/null
@@ -0,0 +1,72 @@
+From foo@baz Tue Sep 29 14:20:47 CEST 2015
+From: Wilson Kok <wkok@cumulusnetworks.com>
+Date: Tue, 22 Sep 2015 21:40:22 -0700
+Subject: fib_rules: fix fib rule dumps across multiple skbs
+
+From: Wilson Kok <wkok@cumulusnetworks.com>
+
+[ 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 <wkok@cumulusnetworks.com>
+Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..b83c189
--- /dev/null
@@ -0,0 +1,35 @@
+From foo@baz Tue Sep 29 14:20:47 CEST 2015
+From: huaibin Wang <huaibin.wang@6wind.com>
+Date: Tue, 25 Aug 2015 16:20:34 +0200
+Subject: ip6_gre: release cached dst on tunnel removal
+
+From: huaibin Wang <huaibin.wang@6wind.com>
+
+[ 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 <xeb@mail.ru>
+Fixes: c12b395a4664 ("gre: Support GRE over IPv6")
+Signed-off-by: huaibin Wang <huaibin.wang@6wind.com>
+Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..08c8ef5
--- /dev/null
@@ -0,0 +1,33 @@
+From foo@baz Tue Sep 29 14:20:47 CEST 2015
+From: Daniel Borkmann <daniel@iogearbox.net>
+Date: Thu, 3 Sep 2015 00:29:07 +0200
+Subject: ipv6: fix exthdrs offload registration in out_rt path
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+[ 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 <daniel@iogearbox.net>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..ba2ce95
--- /dev/null
@@ -0,0 +1,35 @@
+From foo@baz Tue Sep 29 14:20:47 CEST 2015
+From: Richard Laing <richard.laing@alliedtelesis.co.nz>
+Date: Thu, 3 Sep 2015 13:52:31 +1200
+Subject: net/ipv6: Correct PIM6 mrt_lock handling
+
+From: Richard Laing <richard.laing@alliedtelesis.co.nz>
+
+[ 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 <richard.laing@alliedtelesis.co.nz>
+Acked-by: Cong Wang <cwang@twopensource.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..cb39c73
--- /dev/null
@@ -0,0 +1,232 @@
+From foo@baz Tue Sep 29 14:20:47 CEST 2015
+From: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Date: Thu, 10 Sep 2015 17:31:15 -0300
+Subject: sctp: fix race on protocol/netns initialization
+
+From: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+
+[ 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 <vyasevich@gmail.com>
+Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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();
index 1839068d6fa3bb534623c6e548b9e8d6f7b199f3..9bc6579494f060ec96231cdea3b0f03699c8da01 100644 (file)
@@ -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 (file)
index 0000000..88fc9c6
--- /dev/null
@@ -0,0 +1,54 @@
+From foo@baz Tue Sep 29 14:20:47 CEST 2015
+From: Eugene Shatokhin <eugene.shatokhin@rosalab.ru>
+Date: Mon, 24 Aug 2015 23:13:42 +0300
+Subject: usbnet: Get EVENT_NO_RUNTIME_PM bit before it is cleared
+
+From: Eugene Shatokhin <eugene.shatokhin@rosalab.ru>
+
+[ 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 <oneukum@suse.de>.
+
+Signed-off-by: Eugene Shatokhin <eugene.shatokhin@rosalab.ru>
+Acked-by: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);