]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 2 Jun 2017 06:01:40 +0000 (15:01 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 2 Jun 2017 06:01:40 +0000 (15:01 +0900)
added patches:
dccp-tcp-do-not-inherit-mc_list-from-parent.patch
ipv6-check-ip6_find_1stfragopt-return-value-properly.patch
ipv6-fix-out-of-bound-writes-in-__ip6_append_data.patch
ipv6-prevent-overrun-when-parsing-v6-header-options.patch
qmi_wwan-add-another-lenovo-em74xx-device-id.patch
s390-qeth-avoid-null-pointer-dereference-on-osn.patch
s390-qeth-handle-sysfs-error-during-initialization.patch
s390-qeth-unbreak-osm-and-osn-support.patch
sctp-do-not-inherit-ipv6_-mc-ac-fl-_list-from-parent.patch
sctp-fix-icmp-processing-if-skb-is-non-linear.patch
sctp-fix-src-address-selection-if-using-secondary-addresses-for-ipv6.patch
tcp-avoid-fastopen-api-to-be-used-on-af_unspec.patch
tcp-avoid-fragmenting-peculiar-skbs-in-sack.patch
tcp-eliminate-negative-reordering-in-tcp_clean_rtx_queue.patch

15 files changed:
queue-3.18/dccp-tcp-do-not-inherit-mc_list-from-parent.patch [new file with mode: 0644]
queue-3.18/ipv6-check-ip6_find_1stfragopt-return-value-properly.patch [new file with mode: 0644]
queue-3.18/ipv6-fix-out-of-bound-writes-in-__ip6_append_data.patch [new file with mode: 0644]
queue-3.18/ipv6-prevent-overrun-when-parsing-v6-header-options.patch [new file with mode: 0644]
queue-3.18/qmi_wwan-add-another-lenovo-em74xx-device-id.patch [new file with mode: 0644]
queue-3.18/s390-qeth-avoid-null-pointer-dereference-on-osn.patch [new file with mode: 0644]
queue-3.18/s390-qeth-handle-sysfs-error-during-initialization.patch [new file with mode: 0644]
queue-3.18/s390-qeth-unbreak-osm-and-osn-support.patch [new file with mode: 0644]
queue-3.18/sctp-do-not-inherit-ipv6_-mc-ac-fl-_list-from-parent.patch [new file with mode: 0644]
queue-3.18/sctp-fix-icmp-processing-if-skb-is-non-linear.patch [new file with mode: 0644]
queue-3.18/sctp-fix-src-address-selection-if-using-secondary-addresses-for-ipv6.patch [new file with mode: 0644]
queue-3.18/series
queue-3.18/tcp-avoid-fastopen-api-to-be-used-on-af_unspec.patch [new file with mode: 0644]
queue-3.18/tcp-avoid-fragmenting-peculiar-skbs-in-sack.patch [new file with mode: 0644]
queue-3.18/tcp-eliminate-negative-reordering-in-tcp_clean_rtx_queue.patch [new file with mode: 0644]

diff --git a/queue-3.18/dccp-tcp-do-not-inherit-mc_list-from-parent.patch b/queue-3.18/dccp-tcp-do-not-inherit-mc_list-from-parent.patch
new file mode 100644 (file)
index 0000000..66973d6
--- /dev/null
@@ -0,0 +1,42 @@
+From foo@baz Fri Jun  2 12:04:25 JST 2017
+From: Eric Dumazet <edumazet@google.com>
+Date: Tue, 9 May 2017 06:29:19 -0700
+Subject: dccp/tcp: do not inherit mc_list from parent
+
+From: Eric Dumazet <edumazet@google.com>
+
+
+[ Upstream commit 657831ffc38e30092a2d5f03d385d710eb88b09a ]
+
+syzkaller found a way to trigger double frees from ip_mc_drop_socket()
+
+It turns out that leave a copy of parent mc_list at accept() time,
+which is very bad.
+
+Very similar to commit 8b485ce69876 ("tcp: do not inherit
+fastopen_req from parent")
+
+Initial report from Pray3r, completed by Andrey one.
+Thanks a lot to them !
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: Pray3r <pray3r.z@gmail.com>
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Tested-by: Andrey Konovalov <andreyknvl@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/inet_connection_sock.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/ipv4/inet_connection_sock.c
++++ b/net/ipv4/inet_connection_sock.c
+@@ -677,6 +677,8 @@ struct sock *inet_csk_clone_lock(const s
+               inet_sk(newsk)->inet_sport = htons(inet_rsk(req)->ir_num);
+               newsk->sk_write_space = sk_stream_write_space;
++              inet_sk(newsk)->mc_list = NULL;
++
+               newsk->sk_mark = inet_rsk(req)->ir_mark;
+               newicsk->icsk_retransmits = 0;
diff --git a/queue-3.18/ipv6-check-ip6_find_1stfragopt-return-value-properly.patch b/queue-3.18/ipv6-check-ip6_find_1stfragopt-return-value-properly.patch
new file mode 100644 (file)
index 0000000..788de6c
--- /dev/null
@@ -0,0 +1,89 @@
+From foo@baz Fri Jun  2 12:04:25 JST 2017
+From: "David S. Miller" <davem@davemloft.net>
+Date: Wed, 17 May 2017 22:54:11 -0400
+Subject: ipv6: Check ip6_find_1stfragopt() return value properly.
+
+From: "David S. Miller" <davem@davemloft.net>
+
+
+[ Upstream commit 7dd7eb9513bd02184d45f000ab69d78cb1fa1531 ]
+
+Do not use unsigned variables to see if it returns a negative
+error or not.
+
+Fixes: 2423496af35d ("ipv6: Prevent overrun when parsing v6 header options")
+Reported-by: Julia Lawall <julia.lawall@lip6.fr>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/ip6_offload.c |    9 ++++-----
+ net/ipv6/ip6_output.c  |    7 +++----
+ net/ipv6/udp_offload.c |    8 +++++---
+ 3 files changed, 12 insertions(+), 12 deletions(-)
+
+--- a/net/ipv6/ip6_offload.c
++++ b/net/ipv6/ip6_offload.c
+@@ -62,7 +62,6 @@ static struct sk_buff *ipv6_gso_segment(
+       const struct net_offload *ops;
+       int proto;
+       struct frag_hdr *fptr;
+-      unsigned int unfrag_ip6hlen;
+       u8 *prevhdr;
+       int offset = 0;
+       bool encap, udpfrag;
+@@ -121,10 +120,10 @@ static struct sk_buff *ipv6_gso_segment(
+               skb->network_header = (u8 *)ipv6h - skb->head;
+               if (udpfrag) {
+-                      unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
+-                      if (unfrag_ip6hlen < 0)
+-                              return ERR_PTR(unfrag_ip6hlen);
+-                      fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen);
++                      int err = ip6_find_1stfragopt(skb, &prevhdr);
++                      if (err < 0)
++                              return ERR_PTR(err);
++                      fptr = (struct frag_hdr *)((u8 *)ipv6h + err);
+                       fptr->frag_off = htons(offset);
+                       if (skb->next != NULL)
+                               fptr->frag_off |= htons(IP6_MF);
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -569,11 +569,10 @@ int ip6_fragment(struct sk_buff *skb, in
+       u8 *prevhdr, nexthdr = 0;
+       struct net *net = dev_net(skb_dst(skb)->dev);
+-      hlen = ip6_find_1stfragopt(skb, &prevhdr);
+-      if (hlen < 0) {
+-              err = hlen;
++      err = ip6_find_1stfragopt(skb, &prevhdr);
++      if (err < 0)
+               goto fail;
+-      }
++      hlen = err;
+       nexthdr = *prevhdr;
+       mtu = ip6_skb_dst_mtu(skb);
+--- a/net/ipv6/udp_offload.c
++++ b/net/ipv6/udp_offload.c
+@@ -29,6 +29,7 @@ static struct sk_buff *udp6_ufo_fragment
+       u8 frag_hdr_sz = sizeof(struct frag_hdr);
+       __wsum csum;
+       int tnl_hlen;
++      int err;
+       mss = skb_shinfo(skb)->gso_size;
+       if (unlikely(skb->len <= mss))
+@@ -93,9 +94,10 @@ static struct sk_buff *udp6_ufo_fragment
+               /* Find the unfragmentable header and shift it left by frag_hdr_sz
+                * bytes to insert fragment header.
+                */
+-              unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
+-              if (unfrag_ip6hlen < 0)
+-                      return ERR_PTR(unfrag_ip6hlen);
++              err = ip6_find_1stfragopt(skb, &prevhdr);
++              if (err < 0)
++                      return ERR_PTR(err);
++              unfrag_ip6hlen = err;
+               nexthdr = *prevhdr;
+               *prevhdr = NEXTHDR_FRAGMENT;
+               unfrag_len = (skb_network_header(skb) - skb_mac_header(skb)) +
diff --git a/queue-3.18/ipv6-fix-out-of-bound-writes-in-__ip6_append_data.patch b/queue-3.18/ipv6-fix-out-of-bound-writes-in-__ip6_append_data.patch
new file mode 100644 (file)
index 0000000..f4f35d4
--- /dev/null
@@ -0,0 +1,67 @@
+From foo@baz Fri Jun  2 12:04:25 JST 2017
+From: Eric Dumazet <edumazet@google.com>
+Date: Fri, 19 May 2017 14:17:48 -0700
+Subject: ipv6: fix out of bound writes in __ip6_append_data()
+
+From: Eric Dumazet <edumazet@google.com>
+
+
+[ Upstream commit 232cd35d0804cc241eb887bb8d4d9b3b9881c64a ]
+
+Andrey Konovalov and idaifish@gmail.com reported crashes caused by
+one skb shared_info being overwritten from __ip6_append_data()
+
+Andrey program lead to following state :
+
+copy -4200 datalen 2000 fraglen 2040
+maxfraglen 2040 alloclen 2048 transhdrlen 0 offset 0 fraggap 6200
+
+The skb_copy_and_csum_bits(skb_prev, maxfraglen, data + transhdrlen,
+fraggap, 0); is overwriting skb->head and skb_shared_info
+
+Since we apparently detect this rare condition too late, move the
+code earlier to even avoid allocating skb and risking crashes.
+
+Once again, many thanks to Andrey and syzkaller team.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Tested-by: Andrey Konovalov <andreyknvl@google.com>
+Reported-by: <idaifish@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/ip6_output.c |   15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -1376,6 +1376,11 @@ alloc_new_skb:
+                        */
+                       alloclen += sizeof(struct frag_hdr);
++                      copy = datalen - transhdrlen - fraggap;
++                      if (copy < 0) {
++                              err = -EINVAL;
++                              goto error;
++                      }
+                       if (transhdrlen) {
+                               skb = sock_alloc_send_skb(sk,
+                                               alloclen + hh_len,
+@@ -1425,13 +1430,9 @@ alloc_new_skb:
+                               data += fraggap;
+                               pskb_trim_unique(skb_prev, maxfraglen);
+                       }
+-                      copy = datalen - transhdrlen - fraggap;
+-
+-                      if (copy < 0) {
+-                              err = -EINVAL;
+-                              kfree_skb(skb);
+-                              goto error;
+-                      } else if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) {
++                      if (copy > 0 &&
++                          getfrag(from, data + transhdrlen, offset,
++                                  copy, fraggap, skb) < 0) {
+                               err = -EFAULT;
+                               kfree_skb(skb);
+                               goto error;
diff --git a/queue-3.18/ipv6-prevent-overrun-when-parsing-v6-header-options.patch b/queue-3.18/ipv6-prevent-overrun-when-parsing-v6-header-options.patch
new file mode 100644 (file)
index 0000000..e22d53e
--- /dev/null
@@ -0,0 +1,226 @@
+From foo@baz Fri Jun  2 12:04:25 JST 2017
+From: Craig Gallek <kraig@google.com>
+Date: Tue, 16 May 2017 14:36:23 -0400
+Subject: ipv6: Prevent overrun when parsing v6 header options
+
+From: Craig Gallek <kraig@google.com>
+
+
+[ Upstream commit 2423496af35d94a87156b063ea5cedffc10a70a1 ]
+
+The KASAN warning repoted below was discovered with a syzkaller
+program.  The reproducer is basically:
+  int s = socket(AF_INET6, SOCK_RAW, NEXTHDR_HOP);
+  send(s, &one_byte_of_data, 1, MSG_MORE);
+  send(s, &more_than_mtu_bytes_data, 2000, 0);
+
+The socket() call sets the nexthdr field of the v6 header to
+NEXTHDR_HOP, the first send call primes the payload with a non zero
+byte of data, and the second send call triggers the fragmentation path.
+
+The fragmentation code tries to parse the header options in order
+to figure out where to insert the fragment option.  Since nexthdr points
+to an invalid option, the calculation of the size of the network header
+can made to be much larger than the linear section of the skb and data
+is read outside of it.
+
+This fix makes ip6_find_1stfrag return an error if it detects
+running out-of-bounds.
+
+[   42.361487] ==================================================================
+[   42.364412] BUG: KASAN: slab-out-of-bounds in ip6_fragment+0x11c8/0x3730
+[   42.365471] Read of size 840 at addr ffff88000969e798 by task ip6_fragment-oo/3789
+[   42.366469]
+[   42.366696] CPU: 1 PID: 3789 Comm: ip6_fragment-oo Not tainted 4.11.0+ #41
+[   42.367628] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.1-1ubuntu1 04/01/2014
+[   42.368824] Call Trace:
+[   42.369183]  dump_stack+0xb3/0x10b
+[   42.369664]  print_address_description+0x73/0x290
+[   42.370325]  kasan_report+0x252/0x370
+[   42.370839]  ? ip6_fragment+0x11c8/0x3730
+[   42.371396]  check_memory_region+0x13c/0x1a0
+[   42.371978]  memcpy+0x23/0x50
+[   42.372395]  ip6_fragment+0x11c8/0x3730
+[   42.372920]  ? nf_ct_expect_unregister_notifier+0x110/0x110
+[   42.373681]  ? ip6_copy_metadata+0x7f0/0x7f0
+[   42.374263]  ? ip6_forward+0x2e30/0x2e30
+[   42.374803]  ip6_finish_output+0x584/0x990
+[   42.375350]  ip6_output+0x1b7/0x690
+[   42.375836]  ? ip6_finish_output+0x990/0x990
+[   42.376411]  ? ip6_fragment+0x3730/0x3730
+[   42.376968]  ip6_local_out+0x95/0x160
+[   42.377471]  ip6_send_skb+0xa1/0x330
+[   42.377969]  ip6_push_pending_frames+0xb3/0xe0
+[   42.378589]  rawv6_sendmsg+0x2051/0x2db0
+[   42.379129]  ? rawv6_bind+0x8b0/0x8b0
+[   42.379633]  ? _copy_from_user+0x84/0xe0
+[   42.380193]  ? debug_check_no_locks_freed+0x290/0x290
+[   42.380878]  ? ___sys_sendmsg+0x162/0x930
+[   42.381427]  ? rcu_read_lock_sched_held+0xa3/0x120
+[   42.382074]  ? sock_has_perm+0x1f6/0x290
+[   42.382614]  ? ___sys_sendmsg+0x167/0x930
+[   42.383173]  ? lock_downgrade+0x660/0x660
+[   42.383727]  inet_sendmsg+0x123/0x500
+[   42.384226]  ? inet_sendmsg+0x123/0x500
+[   42.384748]  ? inet_recvmsg+0x540/0x540
+[   42.385263]  sock_sendmsg+0xca/0x110
+[   42.385758]  SYSC_sendto+0x217/0x380
+[   42.386249]  ? SYSC_connect+0x310/0x310
+[   42.386783]  ? __might_fault+0x110/0x1d0
+[   42.387324]  ? lock_downgrade+0x660/0x660
+[   42.387880]  ? __fget_light+0xa1/0x1f0
+[   42.388403]  ? __fdget+0x18/0x20
+[   42.388851]  ? sock_common_setsockopt+0x95/0xd0
+[   42.389472]  ? SyS_setsockopt+0x17f/0x260
+[   42.390021]  ? entry_SYSCALL_64_fastpath+0x5/0xbe
+[   42.390650]  SyS_sendto+0x40/0x50
+[   42.391103]  entry_SYSCALL_64_fastpath+0x1f/0xbe
+[   42.391731] RIP: 0033:0x7fbbb711e383
+[   42.392217] RSP: 002b:00007ffff4d34f28 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
+[   42.393235] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fbbb711e383
+[   42.394195] RDX: 0000000000001000 RSI: 00007ffff4d34f60 RDI: 0000000000000003
+[   42.395145] RBP: 0000000000000046 R08: 00007ffff4d34f40 R09: 0000000000000018
+[   42.396056] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000400aad
+[   42.396598] R13: 0000000000000066 R14: 00007ffff4d34ee0 R15: 00007fbbb717af00
+[   42.397257]
+[   42.397411] Allocated by task 3789:
+[   42.397702]  save_stack_trace+0x16/0x20
+[   42.398005]  save_stack+0x46/0xd0
+[   42.398267]  kasan_kmalloc+0xad/0xe0
+[   42.398548]  kasan_slab_alloc+0x12/0x20
+[   42.398848]  __kmalloc_node_track_caller+0xcb/0x380
+[   42.399224]  __kmalloc_reserve.isra.32+0x41/0xe0
+[   42.399654]  __alloc_skb+0xf8/0x580
+[   42.400003]  sock_wmalloc+0xab/0xf0
+[   42.400346]  __ip6_append_data.isra.41+0x2472/0x33d0
+[   42.400813]  ip6_append_data+0x1a8/0x2f0
+[   42.401122]  rawv6_sendmsg+0x11ee/0x2db0
+[   42.401505]  inet_sendmsg+0x123/0x500
+[   42.401860]  sock_sendmsg+0xca/0x110
+[   42.402209]  ___sys_sendmsg+0x7cb/0x930
+[   42.402582]  __sys_sendmsg+0xd9/0x190
+[   42.402941]  SyS_sendmsg+0x2d/0x50
+[   42.403273]  entry_SYSCALL_64_fastpath+0x1f/0xbe
+[   42.403718]
+[   42.403871] Freed by task 1794:
+[   42.404146]  save_stack_trace+0x16/0x20
+[   42.404515]  save_stack+0x46/0xd0
+[   42.404827]  kasan_slab_free+0x72/0xc0
+[   42.405167]  kfree+0xe8/0x2b0
+[   42.405462]  skb_free_head+0x74/0xb0
+[   42.405806]  skb_release_data+0x30e/0x3a0
+[   42.406198]  skb_release_all+0x4a/0x60
+[   42.406563]  consume_skb+0x113/0x2e0
+[   42.406910]  skb_free_datagram+0x1a/0xe0
+[   42.407288]  netlink_recvmsg+0x60d/0xe40
+[   42.407667]  sock_recvmsg+0xd7/0x110
+[   42.408022]  ___sys_recvmsg+0x25c/0x580
+[   42.408395]  __sys_recvmsg+0xd6/0x190
+[   42.408753]  SyS_recvmsg+0x2d/0x50
+[   42.409086]  entry_SYSCALL_64_fastpath+0x1f/0xbe
+[   42.409513]
+[   42.409665] The buggy address belongs to the object at ffff88000969e780
+[   42.409665]  which belongs to the cache kmalloc-512 of size 512
+[   42.410846] The buggy address is located 24 bytes inside of
+[   42.410846]  512-byte region [ffff88000969e780, ffff88000969e980)
+[   42.411941] The buggy address belongs to the page:
+[   42.412405] page:ffffea000025a780 count:1 mapcount:0 mapping:          (null) index:0x0 compound_mapcount: 0
+[   42.413298] flags: 0x100000000008100(slab|head)
+[   42.413729] raw: 0100000000008100 0000000000000000 0000000000000000 00000001800c000c
+[   42.414387] raw: ffffea00002a9500 0000000900000007 ffff88000c401280 0000000000000000
+[   42.415074] page dumped because: kasan: bad access detected
+[   42.415604]
+[   42.415757] Memory state around the buggy address:
+[   42.416222]  ffff88000969e880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[   42.416904]  ffff88000969e900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[   42.417591] >ffff88000969e980: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+[   42.418273]                    ^
+[   42.418588]  ffff88000969ea00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+[   42.419273]  ffff88000969ea80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+[   42.419882] ==================================================================
+
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Signed-off-by: Craig Gallek <kraig@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/ip6_offload.c |    2 ++
+ net/ipv6/ip6_output.c  |    4 ++++
+ net/ipv6/output_core.c |   14 ++++++++------
+ net/ipv6/udp_offload.c |    2 ++
+ 4 files changed, 16 insertions(+), 6 deletions(-)
+
+--- a/net/ipv6/ip6_offload.c
++++ b/net/ipv6/ip6_offload.c
+@@ -122,6 +122,8 @@ static struct sk_buff *ipv6_gso_segment(
+               if (udpfrag) {
+                       unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
++                      if (unfrag_ip6hlen < 0)
++                              return ERR_PTR(unfrag_ip6hlen);
+                       fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen);
+                       fptr->frag_off = htons(offset);
+                       if (skb->next != NULL)
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -570,6 +570,10 @@ int ip6_fragment(struct sk_buff *skb, in
+       struct net *net = dev_net(skb_dst(skb)->dev);
+       hlen = ip6_find_1stfragopt(skb, &prevhdr);
++      if (hlen < 0) {
++              err = hlen;
++              goto fail;
++      }
+       nexthdr = *prevhdr;
+       mtu = ip6_skb_dst_mtu(skb);
+--- a/net/ipv6/output_core.c
++++ b/net/ipv6/output_core.c
+@@ -45,14 +45,13 @@ EXPORT_SYMBOL_GPL(ipv6_proxy_select_iden
+ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
+ {
+       u16 offset = sizeof(struct ipv6hdr);
+-      struct ipv6_opt_hdr *exthdr =
+-                              (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
+       unsigned int packet_len = skb_tail_pointer(skb) -
+               skb_network_header(skb);
+       int found_rhdr = 0;
+       *nexthdr = &ipv6_hdr(skb)->nexthdr;
+-      while (offset + 1 <= packet_len) {
++      while (offset <= packet_len) {
++              struct ipv6_opt_hdr *exthdr;
+               switch (**nexthdr) {
+@@ -73,13 +72,16 @@ int ip6_find_1stfragopt(struct sk_buff *
+                       return offset;
+               }
+-              offset += ipv6_optlen(exthdr);
+-              *nexthdr = &exthdr->nexthdr;
++              if (offset + sizeof(struct ipv6_opt_hdr) > packet_len)
++                      return -EINVAL;
++
+               exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
+                                                offset);
++              offset += ipv6_optlen(exthdr);
++              *nexthdr = &exthdr->nexthdr;
+       }
+-      return offset;
++      return -EINVAL;
+ }
+ EXPORT_SYMBOL(ip6_find_1stfragopt);
+--- a/net/ipv6/udp_offload.c
++++ b/net/ipv6/udp_offload.c
+@@ -94,6 +94,8 @@ static struct sk_buff *udp6_ufo_fragment
+                * bytes to insert fragment header.
+                */
+               unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
++              if (unfrag_ip6hlen < 0)
++                      return ERR_PTR(unfrag_ip6hlen);
+               nexthdr = *prevhdr;
+               *prevhdr = NEXTHDR_FRAGMENT;
+               unfrag_len = (skb_network_header(skb) - skb_mac_header(skb)) +
diff --git a/queue-3.18/qmi_wwan-add-another-lenovo-em74xx-device-id.patch b/queue-3.18/qmi_wwan-add-another-lenovo-em74xx-device-id.patch
new file mode 100644 (file)
index 0000000..a66c6d1
--- /dev/null
@@ -0,0 +1,33 @@
+From foo@baz Fri Jun  2 12:04:25 JST 2017
+From: Bjørn Mork <bjorn@mork.no>
+Date: Wed, 17 May 2017 16:31:41 +0200
+Subject: qmi_wwan: add another Lenovo EM74xx device ID
+
+From: Bjørn Mork <bjorn@mork.no>
+
+
+[ Upstream commit 486181bcb3248e2f1977f4e69387a898234a4e1e ]
+
+In their infinite wisdom, and never ending quest for end user frustration,
+Lenovo has decided to use a new USB device ID for the wwan modules in
+their 2017 laptops.  The actual hardware is still the Sierra Wireless
+EM7455 or EM7430, depending on region.
+
+Signed-off-by: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/usb/qmi_wwan.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -771,6 +771,8 @@ static const struct usb_device_id produc
+       {QMI_FIXED_INTF(0x1199, 0x9071, 10)},   /* Sierra Wireless MC74xx */
+       {QMI_FIXED_INTF(0x1199, 0x9079, 8)},    /* Sierra Wireless EM74xx */
+       {QMI_FIXED_INTF(0x1199, 0x9079, 10)},   /* Sierra Wireless EM74xx */
++      {QMI_FIXED_INTF(0x1199, 0x907b, 8)},    /* Sierra Wireless EM74xx */
++      {QMI_FIXED_INTF(0x1199, 0x907b, 10)},   /* Sierra Wireless EM74xx */
+       {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)},    /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
+       {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)},    /* Alcatel L800MA */
+       {QMI_FIXED_INTF(0x2357, 0x0201, 4)},    /* TP-LINK HSUPA Modem MA180 */
diff --git a/queue-3.18/s390-qeth-avoid-null-pointer-dereference-on-osn.patch b/queue-3.18/s390-qeth-avoid-null-pointer-dereference-on-osn.patch
new file mode 100644 (file)
index 0000000..4ad2557
--- /dev/null
@@ -0,0 +1,46 @@
+From foo@baz Fri Jun  2 12:04:25 JST 2017
+From: Julian Wiedmann <jwi@linux.vnet.ibm.com>
+Date: Wed, 10 May 2017 19:07:53 +0200
+Subject: s390/qeth: avoid null pointer dereference on OSN
+
+From: Julian Wiedmann <jwi@linux.vnet.ibm.com>
+
+
+[ Upstream commit 25e2c341e7818a394da9abc403716278ee646014 ]
+
+Access card->dev only after checking whether's its valid.
+
+Signed-off-by: Julian Wiedmann <jwi@linux.vnet.ibm.com>
+Reviewed-by: Ursula Braun <ubraun@linux.vnet.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/s390/net/qeth_l2_main.c |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/s390/net/qeth_l2_main.c
++++ b/drivers/s390/net/qeth_l2_main.c
+@@ -970,7 +970,6 @@ static int qeth_l2_setup_netdev(struct q
+       case QETH_CARD_TYPE_OSN:
+               card->dev = alloc_netdev(0, "osn%d", NET_NAME_UNKNOWN,
+                                        ether_setup);
+-              card->dev->flags |= IFF_NOARP;
+               break;
+       default:
+               card->dev = alloc_etherdev(0);
+@@ -983,9 +982,12 @@ static int qeth_l2_setup_netdev(struct q
+       card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
+       card->dev->mtu = card->info.initial_mtu;
+       card->dev->netdev_ops = &qeth_l2_netdev_ops;
+-      card->dev->ethtool_ops =
+-              (card->info.type != QETH_CARD_TYPE_OSN) ?
+-              &qeth_l2_ethtool_ops : &qeth_l2_osn_ops;
++      if (card->info.type == QETH_CARD_TYPE_OSN) {
++              card->dev->ethtool_ops = &qeth_l2_osn_ops;
++              card->dev->flags |= IFF_NOARP;
++      } else {
++              card->dev->ethtool_ops = &qeth_l2_ethtool_ops;
++      }
+       card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+       card->info.broadcast_capable = 1;
+       qeth_l2_request_initial_mac(card);
diff --git a/queue-3.18/s390-qeth-handle-sysfs-error-during-initialization.patch b/queue-3.18/s390-qeth-handle-sysfs-error-during-initialization.patch
new file mode 100644 (file)
index 0000000..1bee14a
--- /dev/null
@@ -0,0 +1,82 @@
+From foo@baz Fri Jun  2 12:04:25 JST 2017
+From: Ursula Braun <ubraun@linux.vnet.ibm.com>
+Date: Wed, 10 May 2017 19:07:51 +0200
+Subject: s390/qeth: handle sysfs error during initialization
+
+From: Ursula Braun <ubraun@linux.vnet.ibm.com>
+
+
+[ Upstream commit 9111e7880ccf419548c7b0887df020b08eadb075 ]
+
+When setting up the device from within the layer discipline's
+probe routine, creating the layer-specific sysfs attributes can fail.
+Report this error back to the caller, and handle it by
+releasing the layer discipline.
+
+Signed-off-by: Ursula Braun <ubraun@linux.vnet.ibm.com>
+[jwi: updated commit msg, moved an OSN change to a subsequent patch]
+Signed-off-by: Julian Wiedmann <jwi@linux.vnet.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/s390/net/qeth_core_main.c |    4 +++-
+ drivers/s390/net/qeth_core_sys.c  |    2 ++
+ drivers/s390/net/qeth_l2_main.c   |    5 ++++-
+ drivers/s390/net/qeth_l3_main.c   |    5 ++++-
+ 4 files changed, 13 insertions(+), 3 deletions(-)
+
+--- a/drivers/s390/net/qeth_core_main.c
++++ b/drivers/s390/net/qeth_core_main.c
+@@ -5505,8 +5505,10 @@ static int qeth_core_set_online(struct c
+               if (rc)
+                       goto err;
+               rc = card->discipline->setup(card->gdev);
+-              if (rc)
++              if (rc) {
++                      qeth_core_free_discipline(card);
+                       goto err;
++              }
+       }
+       rc = card->discipline->set_online(gdev);
+ err:
+--- a/drivers/s390/net/qeth_core_sys.c
++++ b/drivers/s390/net/qeth_core_sys.c
+@@ -459,6 +459,8 @@ static ssize_t qeth_dev_layer2_store(str
+               goto out;
+       rc = card->discipline->setup(card->gdev);
++      if (rc)
++              qeth_core_free_discipline(card);
+ out:
+       mutex_unlock(&card->discipline_mutex);
+       return rc ? rc : count;
+--- a/drivers/s390/net/qeth_l2_main.c
++++ b/drivers/s390/net/qeth_l2_main.c
+@@ -890,8 +890,11 @@ static int qeth_l2_stop(struct net_devic
+ static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
+ {
+       struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++      int rc;
+-      qeth_l2_create_device_attributes(&gdev->dev);
++      rc = qeth_l2_create_device_attributes(&gdev->dev);
++      if (rc)
++              return rc;
+       INIT_LIST_HEAD(&card->vid_list);
+       INIT_LIST_HEAD(&card->mc_list);
+       card->options.layer2 = 1;
+--- a/drivers/s390/net/qeth_l3_main.c
++++ b/drivers/s390/net/qeth_l3_main.c
+@@ -3317,8 +3317,11 @@ static int qeth_l3_setup_netdev(struct q
+ static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
+ {
+       struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++      int rc;
+-      qeth_l3_create_device_attributes(&gdev->dev);
++      rc = qeth_l3_create_device_attributes(&gdev->dev);
++      if (rc)
++              return rc;
+       card->options.layer2 = 0;
+       card->info.hwtrap = 0;
+       return 0;
diff --git a/queue-3.18/s390-qeth-unbreak-osm-and-osn-support.patch b/queue-3.18/s390-qeth-unbreak-osm-and-osn-support.patch
new file mode 100644 (file)
index 0000000..680f0b2
--- /dev/null
@@ -0,0 +1,263 @@
+From foo@baz Fri Jun  2 12:04:25 JST 2017
+From: Julian Wiedmann <jwi@linux.vnet.ibm.com>
+Date: Wed, 10 May 2017 19:07:52 +0200
+Subject: s390/qeth: unbreak OSM and OSN support
+
+From: Julian Wiedmann <jwi@linux.vnet.ibm.com>
+
+
+[ Upstream commit 2d2ebb3ed0c6acfb014f98e427298673a5d07b82 ]
+
+commit b4d72c08b358 ("qeth: bridgeport support - basic control")
+broke the support for OSM and OSN devices as follows:
+
+As OSM and OSN are L2 only, qeth_core_probe_device() does an early
+setup by loading the l2 discipline and calling qeth_l2_probe_device().
+In this context, adding the l2-specific bridgeport sysfs attributes
+via qeth_l2_create_device_attributes() hits a BUG_ON in fs/sysfs/group.c,
+since the basic sysfs infrastructure for the device hasn't been
+established yet.
+
+Note that OSN actually has its own unique sysfs attributes
+(qeth_osn_devtype), so the additional attributes shouldn't be created
+at all.
+For OSM, add a new qeth_l2_devtype that contains all the common
+and l2-specific sysfs attributes.
+When qeth_core_probe_device() does early setup for OSM or OSN, assign
+the corresponding devtype so that the ccwgroup probe code creates the
+full set of sysfs attributes.
+This allows us to skip qeth_l2_create_device_attributes() in case
+of an early setup.
+
+Any device that can't do early setup will initially have only the
+generic sysfs attributes, and when it's probed later
+qeth_l2_probe_device() adds the l2-specific attributes.
+
+If an early-setup device is removed (by calling ccwgroup_ungroup()),
+device_unregister() will - using the devtype - delete the
+l2-specific attributes before qeth_l2_remove_device() is called.
+So make sure to not remove them twice.
+
+What complicates the issue is that qeth_l2_probe_device() and
+qeth_l2_remove_device() is also called on a device when its
+layer2 attribute changes (ie. its layer mode is switched).
+For early-setup devices this wouldn't work properly - we wouldn't
+remove the l2-specific attributes when switching to L3.
+But switching the layer mode doesn't actually make any sense;
+we already decided that the device can only operate in L2!
+So just refuse to switch the layer mode on such devices. Note that
+OSN doesn't have a layer2 attribute, so we only need to special-case
+OSM.
+
+Based on an initial patch by Ursula Braun.
+
+Fixes: b4d72c08b358 ("qeth: bridgeport support - basic control")
+Signed-off-by: Julian Wiedmann <jwi@linux.vnet.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/s390/net/qeth_core.h      |    4 ++++
+ drivers/s390/net/qeth_core_main.c |   17 +++++++++--------
+ drivers/s390/net/qeth_core_sys.c  |   22 ++++++++++++++--------
+ drivers/s390/net/qeth_l2.h        |    2 ++
+ drivers/s390/net/qeth_l2_main.c   |   17 +++++++++++++----
+ drivers/s390/net/qeth_l2_sys.c    |    8 ++++++++
+ drivers/s390/net/qeth_l3_main.c   |    1 +
+ 7 files changed, 51 insertions(+), 20 deletions(-)
+
+--- a/drivers/s390/net/qeth_core.h
++++ b/drivers/s390/net/qeth_core.h
+@@ -722,6 +722,7 @@ enum qeth_discipline_id {
+ };
+ struct qeth_discipline {
++      const struct device_type *devtype;
+       void (*start_poll)(struct ccw_device *, int, unsigned long);
+       qdio_handler_t *input_handler;
+       qdio_handler_t *output_handler;
+@@ -887,6 +888,9 @@ extern struct qeth_discipline qeth_l2_di
+ extern struct qeth_discipline qeth_l3_discipline;
+ extern const struct attribute_group *qeth_generic_attr_groups[];
+ extern const struct attribute_group *qeth_osn_attr_groups[];
++extern const struct attribute_group qeth_device_attr_group;
++extern const struct attribute_group qeth_device_blkt_group;
++extern const struct device_type qeth_generic_devtype;
+ extern struct workqueue_struct *qeth_wq;
+ int qeth_card_hw_is_reachable(struct qeth_card *);
+--- a/drivers/s390/net/qeth_core_main.c
++++ b/drivers/s390/net/qeth_core_main.c
+@@ -5304,10 +5304,12 @@ void qeth_core_free_discipline(struct qe
+       card->discipline = NULL;
+ }
+-static const struct device_type qeth_generic_devtype = {
++const struct device_type qeth_generic_devtype = {
+       .name = "qeth_generic",
+       .groups = qeth_generic_attr_groups,
+ };
++EXPORT_SYMBOL_GPL(qeth_generic_devtype);
++
+ static const struct device_type qeth_osn_devtype = {
+       .name = "qeth_osn",
+       .groups = qeth_osn_attr_groups,
+@@ -5433,23 +5435,22 @@ static int qeth_core_probe_device(struct
+               goto err_card;
+       }
+-      if (card->info.type == QETH_CARD_TYPE_OSN)
+-              gdev->dev.type = &qeth_osn_devtype;
+-      else
+-              gdev->dev.type = &qeth_generic_devtype;
+-
+       switch (card->info.type) {
+       case QETH_CARD_TYPE_OSN:
+       case QETH_CARD_TYPE_OSM:
+               rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
+               if (rc)
+                       goto err_card;
++
++              gdev->dev.type = (card->info.type != QETH_CARD_TYPE_OSN)
++                                      ? card->discipline->devtype
++                                      : &qeth_osn_devtype;
+               rc = card->discipline->setup(card->gdev);
+               if (rc)
+                       goto err_disc;
+-      case QETH_CARD_TYPE_OSD:
+-      case QETH_CARD_TYPE_OSX:
++              break;
+       default:
++              gdev->dev.type = &qeth_generic_devtype;
+               break;
+       }
+--- a/drivers/s390/net/qeth_core_sys.c
++++ b/drivers/s390/net/qeth_core_sys.c
+@@ -446,12 +446,16 @@ static ssize_t qeth_dev_layer2_store(str
+       if (card->options.layer2 == newdis)
+               goto out;
+-      else {
+-              card->info.mac_bits  = 0;
+-              if (card->discipline) {
+-                      card->discipline->remove(card->gdev);
+-                      qeth_core_free_discipline(card);
+-              }
++      if (card->info.type == QETH_CARD_TYPE_OSM) {
++              /* fixed layer, can't switch */
++              rc = -EOPNOTSUPP;
++              goto out;
++      }
++
++      card->info.mac_bits = 0;
++      if (card->discipline) {
++              card->discipline->remove(card->gdev);
++              qeth_core_free_discipline(card);
+       }
+       rc = qeth_core_load_discipline(card, newdis);
+@@ -745,10 +749,11 @@ static struct attribute *qeth_blkt_devic
+       &dev_attr_inter_jumbo.attr,
+       NULL,
+ };
+-static struct attribute_group qeth_device_blkt_group = {
++const struct attribute_group qeth_device_blkt_group = {
+       .name = "blkt",
+       .attrs = qeth_blkt_device_attrs,
+ };
++EXPORT_SYMBOL_GPL(qeth_device_blkt_group);
+ static struct attribute *qeth_device_attrs[] = {
+       &dev_attr_state.attr,
+@@ -768,9 +773,10 @@ static struct attribute *qeth_device_att
+       &dev_attr_switch_attrs.attr,
+       NULL,
+ };
+-static struct attribute_group qeth_device_attr_group = {
++const struct attribute_group qeth_device_attr_group = {
+       .attrs = qeth_device_attrs,
+ };
++EXPORT_SYMBOL_GPL(qeth_device_attr_group);
+ const struct attribute_group *qeth_generic_attr_groups[] = {
+       &qeth_device_attr_group,
+--- a/drivers/s390/net/qeth_l2.h
++++ b/drivers/s390/net/qeth_l2.h
+@@ -8,6 +8,8 @@
+ #include "qeth_core.h"
++extern const struct attribute_group *qeth_l2_attr_groups[];
++
+ int qeth_l2_create_device_attributes(struct device *);
+ void qeth_l2_remove_device_attributes(struct device *);
+ void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card);
+--- a/drivers/s390/net/qeth_l2_main.c
++++ b/drivers/s390/net/qeth_l2_main.c
+@@ -887,14 +887,21 @@ static int qeth_l2_stop(struct net_devic
+       return 0;
+ }
++static const struct device_type qeth_l2_devtype = {
++      .name = "qeth_layer2",
++      .groups = qeth_l2_attr_groups,
++};
++
+ static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
+ {
+       struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+       int rc;
+-      rc = qeth_l2_create_device_attributes(&gdev->dev);
+-      if (rc)
+-              return rc;
++      if (gdev->dev.type == &qeth_generic_devtype) {
++              rc = qeth_l2_create_device_attributes(&gdev->dev);
++              if (rc)
++                      return rc;
++      }
+       INIT_LIST_HEAD(&card->vid_list);
+       INIT_LIST_HEAD(&card->mc_list);
+       card->options.layer2 = 1;
+@@ -906,7 +913,8 @@ static void qeth_l2_remove_device(struct
+ {
+       struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
+-      qeth_l2_remove_device_attributes(&cgdev->dev);
++      if (cgdev->dev.type == &qeth_generic_devtype)
++              qeth_l2_remove_device_attributes(&cgdev->dev);
+       qeth_set_allowed_threads(card, 0, 1);
+       wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
+@@ -1276,6 +1284,7 @@ static int qeth_l2_control_event(struct
+ }
+ struct qeth_discipline qeth_l2_discipline = {
++      .devtype = &qeth_l2_devtype,
+       .start_poll = qeth_qdio_start_poll,
+       .input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
+       .output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
+--- a/drivers/s390/net/qeth_l2_sys.c
++++ b/drivers/s390/net/qeth_l2_sys.c
+@@ -216,3 +216,11 @@ void qeth_l2_setup_bridgeport_attrs(stru
+       } else
+               qeth_bridgeport_an_set(card, 0);
+ }
++
++const struct attribute_group *qeth_l2_attr_groups[] = {
++      &qeth_device_attr_group,
++      &qeth_device_blkt_group,
++      /* l2 specific, see l2_{create,remove}_device_attributes(): */
++      &qeth_l2_bridgeport_attr_group,
++      NULL,
++};
+--- a/drivers/s390/net/qeth_l3_main.c
++++ b/drivers/s390/net/qeth_l3_main.c
+@@ -3612,6 +3612,7 @@ static int qeth_l3_control_event(struct
+ }
+ struct qeth_discipline qeth_l3_discipline = {
++      .devtype = &qeth_generic_devtype,
+       .start_poll = qeth_qdio_start_poll,
+       .input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
+       .output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
diff --git a/queue-3.18/sctp-do-not-inherit-ipv6_-mc-ac-fl-_list-from-parent.patch b/queue-3.18/sctp-do-not-inherit-ipv6_-mc-ac-fl-_list-from-parent.patch
new file mode 100644 (file)
index 0000000..5d61102
--- /dev/null
@@ -0,0 +1,34 @@
+From foo@baz Fri Jun  2 12:04:25 JST 2017
+From: Eric Dumazet <edumazet@google.com>
+Date: Wed, 17 May 2017 07:16:40 -0700
+Subject: sctp: do not inherit ipv6_{mc|ac|fl}_list from parent
+
+From: Eric Dumazet <edumazet@google.com>
+
+
+[ Upstream commit fdcee2cbb8438702ea1b328fb6e0ac5e9a40c7f8 ]
+
+SCTP needs fixes similar to 83eaddab4378 ("ipv6/dccp: do not inherit
+ipv6_mc_list from parent"), otherwise bad things can happen.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Tested-by: Andrey Konovalov <andreyknvl@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/ipv6.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/net/sctp/ipv6.c
++++ b/net/sctp/ipv6.c
+@@ -673,6 +673,9 @@ static struct sock *sctp_v6_create_accep
+       newnp = inet6_sk(newsk);
+       memcpy(newnp, np, sizeof(struct ipv6_pinfo));
++      newnp->ipv6_mc_list = NULL;
++      newnp->ipv6_ac_list = NULL;
++      newnp->ipv6_fl_list = NULL;
+       rcu_read_lock();
+       opt = rcu_dereference(np->opt);
diff --git a/queue-3.18/sctp-fix-icmp-processing-if-skb-is-non-linear.patch b/queue-3.18/sctp-fix-icmp-processing-if-skb-is-non-linear.patch
new file mode 100644 (file)
index 0000000..c3c578c
--- /dev/null
@@ -0,0 +1,72 @@
+From foo@baz Fri Jun  2 12:04:25 JST 2017
+From: Davide Caratti <dcaratti@redhat.com>
+Date: Thu, 25 May 2017 19:14:56 +0200
+Subject: sctp: fix ICMP processing if skb is non-linear
+
+From: Davide Caratti <dcaratti@redhat.com>
+
+
+[ Upstream commit 804ec7ebe8ea003999ca8d1bfc499edc6a9e07df ]
+
+sometimes ICMP replies to INIT chunks are ignored by the client, even if
+the encapsulated SCTP headers match an open socket. This happens when the
+ICMP packet is carried by a paged skb: use skb_header_pointer() to read
+packet contents beyond the SCTP header, so that chunk header and initiate
+tag are validated correctly.
+
+v2:
+- don't use skb_header_pointer() to read the transport header, since
+  icmp_socket_deliver() already puts these 8 bytes in the linear area.
+- change commit message to make specific reference to INIT chunks.
+
+Signed-off-by: Davide Caratti <dcaratti@redhat.com>
+Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Acked-by: Vlad Yasevich <vyasevich@gmail.com>
+Reviewed-by: Xin Long <lucien.xin@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/input.c |   16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+--- a/net/sctp/input.c
++++ b/net/sctp/input.c
+@@ -472,15 +472,14 @@ struct sock *sctp_err_lookup(struct net
+                            struct sctp_association **app,
+                            struct sctp_transport **tpp)
+ {
++      struct sctp_init_chunk *chunkhdr, _chunkhdr;
+       union sctp_addr saddr;
+       union sctp_addr daddr;
+       struct sctp_af *af;
+       struct sock *sk = NULL;
+       struct sctp_association *asoc;
+       struct sctp_transport *transport = NULL;
+-      struct sctp_init_chunk *chunkhdr;
+       __u32 vtag = ntohl(sctphdr->vtag);
+-      int len = skb->len - ((void *)sctphdr - (void *)skb->data);
+       *app = NULL; *tpp = NULL;
+@@ -515,13 +514,16 @@ struct sock *sctp_err_lookup(struct net
+        * discard the packet.
+        */
+       if (vtag == 0) {
+-              chunkhdr = (void *)sctphdr + sizeof(struct sctphdr);
+-              if (len < sizeof(struct sctphdr) + sizeof(sctp_chunkhdr_t)
+-                        + sizeof(__be32) ||
++              /* chunk header + first 4 octects of init header */
++              chunkhdr = skb_header_pointer(skb, skb_transport_offset(skb) +
++                                            sizeof(struct sctphdr),
++                                            sizeof(struct sctp_chunkhdr) +
++                                            sizeof(__be32), &_chunkhdr);
++              if (!chunkhdr ||
+                   chunkhdr->chunk_hdr.type != SCTP_CID_INIT ||
+-                  ntohl(chunkhdr->init_hdr.init_tag) != asoc->c.my_vtag) {
++                  ntohl(chunkhdr->init_hdr.init_tag) != asoc->c.my_vtag)
+                       goto out;
+-              }
++
+       } else if (vtag != asoc->c.peer_vtag) {
+               goto out;
+       }
diff --git a/queue-3.18/sctp-fix-src-address-selection-if-using-secondary-addresses-for-ipv6.patch b/queue-3.18/sctp-fix-src-address-selection-if-using-secondary-addresses-for-ipv6.patch
new file mode 100644 (file)
index 0000000..35e5c69
--- /dev/null
@@ -0,0 +1,119 @@
+From foo@baz Fri Jun  2 12:04:25 JST 2017
+From: Xin Long <lucien.xin@gmail.com>
+Date: Fri, 12 May 2017 14:39:52 +0800
+Subject: sctp: fix src address selection if using secondary addresses for ipv6
+
+From: Xin Long <lucien.xin@gmail.com>
+
+
+[ Upstream commit dbc2b5e9a09e9a6664679a667ff81cff6e5f2641 ]
+
+Commit 0ca50d12fe46 ("sctp: fix src address selection if using secondary
+addresses") has fixed a src address selection issue when using secondary
+addresses for ipv4.
+
+Now sctp ipv6 also has the similar issue. When using a secondary address,
+sctp_v6_get_dst tries to choose the saddr which has the most same bits
+with the daddr by sctp_v6_addr_match_len. It may make some cases not work
+as expected.
+
+hostA:
+  [1] fd21:356b:459a:cf10::11 (eth1)
+  [2] fd21:356b:459a:cf20::11 (eth2)
+
+hostB:
+  [a] fd21:356b:459a:cf30::2  (eth1)
+  [b] fd21:356b:459a:cf40::2  (eth2)
+
+route from hostA to hostB:
+  fd21:356b:459a:cf30::/64 dev eth1  metric 1024  mtu 1500
+
+The expected path should be:
+  fd21:356b:459a:cf10::11 <-> fd21:356b:459a:cf30::2
+But addr[2] matches addr[a] more bits than addr[1] does, according to
+sctp_v6_addr_match_len. It causes the path to be:
+  fd21:356b:459a:cf20::11 <-> fd21:356b:459a:cf30::2
+
+This patch is to fix it with the same way as Marcelo's fix for sctp ipv4.
+As no ip_dev_find for ipv6, this patch is to use ipv6_chk_addr to check
+if the saddr is in a dev instead.
+
+Note that for backwards compatibility, it will still do the addr_match_len
+check here when no optimal is found.
+
+Reported-by: Patrick Talbert <ptalbert@redhat.com>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/ipv6.c |   46 +++++++++++++++++++++++++++++-----------------
+ 1 file changed, 29 insertions(+), 17 deletions(-)
+
+--- a/net/sctp/ipv6.c
++++ b/net/sctp/ipv6.c
+@@ -239,12 +239,10 @@ static void sctp_v6_get_dst(struct sctp_
+       struct sctp_bind_addr *bp;
+       struct ipv6_pinfo *np = inet6_sk(sk);
+       struct sctp_sockaddr_entry *laddr;
+-      union sctp_addr *baddr = NULL;
+       union sctp_addr *daddr = &t->ipaddr;
+       union sctp_addr dst_saddr;
+       struct in6_addr *final_p, final;
+       __u8 matchlen = 0;
+-      __u8 bmatchlen;
+       sctp_scope_t scope;
+       memset(fl6, 0, sizeof(struct flowi6));
+@@ -311,23 +309,37 @@ static void sctp_v6_get_dst(struct sctp_
+        */
+       rcu_read_lock();
+       list_for_each_entry_rcu(laddr, &bp->address_list, list) {
+-              if (!laddr->valid)
++              struct dst_entry *bdst;
++              __u8 bmatchlen;
++
++              if (!laddr->valid ||
++                  laddr->state != SCTP_ADDR_SRC ||
++                  laddr->a.sa.sa_family != AF_INET6 ||
++                  scope > sctp_scope(&laddr->a))
+                       continue;
+-              if ((laddr->state == SCTP_ADDR_SRC) &&
+-                  (laddr->a.sa.sa_family == AF_INET6) &&
+-                  (scope <= sctp_scope(&laddr->a))) {
+-                      bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
+-                      if (!baddr || (matchlen < bmatchlen)) {
+-                              baddr = &laddr->a;
+-                              matchlen = bmatchlen;
+-                      }
+-              }
+-      }
+-      if (baddr) {
+-              fl6->saddr = baddr->v6.sin6_addr;
+-              fl6->fl6_sport = baddr->v6.sin6_port;
++
++              fl6->saddr = laddr->a.v6.sin6_addr;
++              fl6->fl6_sport = laddr->a.v6.sin6_port;
+               final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);
+-              dst = ip6_dst_lookup_flow(sk, fl6, final_p);
++              bdst = ip6_dst_lookup_flow(sk, fl6, final_p);
++
++              if (!IS_ERR(bdst) &&
++                  ipv6_chk_addr(dev_net(bdst->dev),
++                                &laddr->a.v6.sin6_addr, bdst->dev, 1)) {
++                      if (!IS_ERR_OR_NULL(dst))
++                              dst_release(dst);
++                      dst = bdst;
++                      break;
++              }
++
++              bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
++              if (matchlen > bmatchlen)
++                      continue;
++
++              if (!IS_ERR_OR_NULL(dst))
++                      dst_release(dst);
++              dst = bdst;
++              matchlen = bmatchlen;
+       }
+       rcu_read_unlock();
index 859878b1edf0bf39a61d21a802d38f75baee41a9..8c399be96ea5217f123eb3738c71aabc2500f6d0 100644 (file)
@@ -1,2 +1,16 @@
 revert-stackprotector-increase-the-per-task-stack-canary-s-random-range-from-32-bits-to-64-bits-on-64-bit-platforms.patch
 netem-fix-skb_orphan_partial.patch
+dccp-tcp-do-not-inherit-mc_list-from-parent.patch
+s390-qeth-handle-sysfs-error-during-initialization.patch
+s390-qeth-unbreak-osm-and-osn-support.patch
+s390-qeth-avoid-null-pointer-dereference-on-osn.patch
+tcp-avoid-fragmenting-peculiar-skbs-in-sack.patch
+sctp-fix-src-address-selection-if-using-secondary-addresses-for-ipv6.patch
+sctp-do-not-inherit-ipv6_-mc-ac-fl-_list-from-parent.patch
+tcp-eliminate-negative-reordering-in-tcp_clean_rtx_queue.patch
+ipv6-prevent-overrun-when-parsing-v6-header-options.patch
+ipv6-check-ip6_find_1stfragopt-return-value-properly.patch
+qmi_wwan-add-another-lenovo-em74xx-device-id.patch
+ipv6-fix-out-of-bound-writes-in-__ip6_append_data.patch
+tcp-avoid-fastopen-api-to-be-used-on-af_unspec.patch
+sctp-fix-icmp-processing-if-skb-is-non-linear.patch
diff --git a/queue-3.18/tcp-avoid-fastopen-api-to-be-used-on-af_unspec.patch b/queue-3.18/tcp-avoid-fastopen-api-to-be-used-on-af_unspec.patch
new file mode 100644 (file)
index 0000000..5c032de
--- /dev/null
@@ -0,0 +1,88 @@
+From foo@baz Fri Jun  2 12:04:25 JST 2017
+From: Wei Wang <weiwan@google.com>
+Date: Wed, 24 May 2017 09:59:31 -0700
+Subject: tcp: avoid fastopen API to be used on AF_UNSPEC
+
+From: Wei Wang <weiwan@google.com>
+
+
+[ Upstream commit ba615f675281d76fd19aa03558777f81fb6b6084 ]
+
+Fastopen API should be used to perform fastopen operations on the TCP
+socket. It does not make sense to use fastopen API to perform disconnect
+by calling it with AF_UNSPEC. The fastopen data path is also prone to
+race conditions and bugs when using with AF_UNSPEC.
+
+One issue reported and analyzed by Vegard Nossum is as follows:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Thread A:                            Thread B:
+------------------------------------------------------------------------
+sendto()
+ - tcp_sendmsg()
+     - sk_stream_memory_free() = 0
+         - goto wait_for_sndbuf
+            - sk_stream_wait_memory()
+               - sk_wait_event() // sleep
+          |                          sendto(flags=MSG_FASTOPEN, dest_addr=AF_UNSPEC)
+         |                           - tcp_sendmsg()
+         |                              - tcp_sendmsg_fastopen()
+         |                                 - __inet_stream_connect()
+         |                                    - tcp_disconnect() //because of AF_UNSPEC
+         |                                       - tcp_transmit_skb()// send RST
+         |                                    - return 0; // no reconnect!
+         |                           - sk_stream_wait_connect()
+         |                                 - sock_error()
+         |                                    - xchg(&sk->sk_err, 0)
+         |                                    - return -ECONNRESET
+       - ... // wake up, see sk->sk_err == 0
+    - skb_entail() on TCP_CLOSE socket
+
+If the connection is reopened then we will send a brand new SYN packet
+after thread A has already queued a buffer. At this point I think the
+socket internal state (sequence numbers etc.) becomes messed up.
+
+When the new connection is closed, the FIN-ACK is rejected because the
+sequence number is outside the window. The other side tries to
+retransmit,
+but __tcp_retransmit_skb() calls tcp_trim_head() on an empty skb which
+corrupts the skb data length and hits a BUG() in copy_and_csum_bits().
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Hence, this patch adds a check for AF_UNSPEC in the fastopen data path
+and return EOPNOTSUPP to user if such case happens.
+
+Fixes: cf60af03ca4e7 ("tcp: Fast Open client - sendmsg(MSG_FASTOPEN)")
+Reported-by: Vegard Nossum <vegard.nossum@oracle.com>
+Signed-off-by: Wei Wang <weiwan@google.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp.c |    7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -1066,9 +1066,12 @@ static int tcp_sendmsg_fastopen(struct s
+                               int *copied, size_t size)
+ {
+       struct tcp_sock *tp = tcp_sk(sk);
++      struct sockaddr *uaddr = msg->msg_name;
+       int err, flags;
+-      if (!(sysctl_tcp_fastopen & TFO_CLIENT_ENABLE))
++      if (!(sysctl_tcp_fastopen & TFO_CLIENT_ENABLE) ||
++          (uaddr && msg->msg_namelen >= sizeof(uaddr->sa_family) &&
++           uaddr->sa_family == AF_UNSPEC))
+               return -EOPNOTSUPP;
+       if (tp->fastopen_req != NULL)
+               return -EALREADY; /* Another Fast Open is in progress */
+@@ -1081,7 +1084,7 @@ static int tcp_sendmsg_fastopen(struct s
+       tp->fastopen_req->size = size;
+       flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0;
+-      err = __inet_stream_connect(sk->sk_socket, msg->msg_name,
++      err = __inet_stream_connect(sk->sk_socket, uaddr,
+                                   msg->msg_namelen, flags);
+       *copied = tp->fastopen_req->copied;
+       tcp_free_fastopen_req(tp);
diff --git a/queue-3.18/tcp-avoid-fragmenting-peculiar-skbs-in-sack.patch b/queue-3.18/tcp-avoid-fragmenting-peculiar-skbs-in-sack.patch
new file mode 100644 (file)
index 0000000..5eadeba
--- /dev/null
@@ -0,0 +1,55 @@
+From foo@baz Fri Jun  2 12:04:25 JST 2017
+From: Yuchung Cheng <ycheng@google.com>
+Date: Wed, 10 May 2017 17:01:27 -0700
+Subject: tcp: avoid fragmenting peculiar skbs in SACK
+
+From: Yuchung Cheng <ycheng@google.com>
+
+
+[ Upstream commit b451e5d24ba6687c6f0e7319c727a709a1846c06 ]
+
+This patch fixes a bug in splitting an SKB during SACK
+processing. Specifically if an skb contains multiple
+packets and is only partially sacked in the higher sequences,
+tcp_match_sack_to_skb() splits the skb and marks the second fragment
+as SACKed.
+
+The current code further attempts rounding up the first fragment
+to MSS boundaries. But it misses a boundary condition when the
+rounded-up fragment size (pkt_len) is exactly skb size.  Spliting
+such an skb is pointless and causses a kernel warning and aborts
+the SACK processing. This patch universally checks such over-split
+before calling tcp_fragment to prevent these unnecessary warnings.
+
+Fixes: adb92db857ee ("tcp: Make SACK code to split only at mss boundaries")
+Signed-off-by: Yuchung Cheng <ycheng@google.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: Soheil Hassas Yeganeh <soheil@google.com>
+Acked-by: Neal Cardwell <ncardwell@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp_input.c |    9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -1171,13 +1171,14 @@ static int tcp_match_skb_to_sack(struct
+                */
+               if (pkt_len > mss) {
+                       unsigned int new_len = (pkt_len / mss) * mss;
+-                      if (!in_sack && new_len < pkt_len) {
++                      if (!in_sack && new_len < pkt_len)
+                               new_len += mss;
+-                              if (new_len >= skb->len)
+-                                      return 0;
+-                      }
+                       pkt_len = new_len;
+               }
++
++              if (pkt_len >= skb->len && !in_sack)
++                      return 0;
++
+               err = tcp_fragment(sk, skb, pkt_len, mss, GFP_ATOMIC);
+               if (err < 0)
+                       return err;
diff --git a/queue-3.18/tcp-eliminate-negative-reordering-in-tcp_clean_rtx_queue.patch b/queue-3.18/tcp-eliminate-negative-reordering-in-tcp_clean_rtx_queue.patch
new file mode 100644 (file)
index 0000000..3d2a248
--- /dev/null
@@ -0,0 +1,44 @@
+From foo@baz Fri Jun  2 12:04:25 JST 2017
+From: Soheil Hassas Yeganeh <soheil@google.com>
+Date: Mon, 15 May 2017 17:05:47 -0400
+Subject: tcp: eliminate negative reordering in tcp_clean_rtx_queue
+
+From: Soheil Hassas Yeganeh <soheil@google.com>
+
+
+[ Upstream commit bafbb9c73241760023d8981191ddd30bb1c6dbac ]
+
+tcp_ack() can call tcp_fragment() which may dededuct the
+value tp->fackets_out when MSS changes. When prior_fackets
+is larger than tp->fackets_out, tcp_clean_rtx_queue() can
+invoke tcp_update_reordering() with negative values. This
+results in absurd tp->reodering values higher than
+sysctl_tcp_max_reordering.
+
+Note that tcp_update_reordering indeeds sets tp->reordering
+to min(sysctl_tcp_max_reordering, metric), but because
+the comparison is signed, a negative metric always wins.
+
+Fixes: c7caf8d3ed7a ("[TCP]: Fix reord detection due to snd_una covered holes")
+Reported-by: Rebecca Isaacs <risaacs@google.com>
+Signed-off-by: Soheil Hassas Yeganeh <soheil@google.com>
+Signed-off-by: Neal Cardwell <ncardwell@google.com>
+Signed-off-by: Yuchung Cheng <ycheng@google.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp_input.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -3173,7 +3173,7 @@ static int tcp_clean_rtx_queue(struct so
+                       int delta;
+                       /* Non-retransmitted hole got filled? That's reordering */
+-                      if (reord < prior_fackets)
++                      if (reord < prior_fackets && reord <= tp->fackets_out)
+                               tcp_update_reordering(sk, tp->fackets_out - reord, 0);
+                       delta = tcp_is_fack(tp) ? pkts_acked :