]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.18 stuff
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Feb 2017 14:37:35 +0000 (15:37 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Feb 2017 14:37:35 +0000 (15:37 +0100)
16 files changed:
queue-3.18/can-fix-kernel-panic-at-security_sock_rcv_skb.patch [new file with mode: 0644]
queue-3.18/ip6_gre-fix-ip6gre_err-invalid-reads.patch [new file with mode: 0644]
queue-3.18/ipv4-keep-skb-dst-around-in-presence-of-ip-options.patch [new file with mode: 0644]
queue-3.18/ipv6-fix-ip6_tnl_parse_tlv_enc_lim.patch [new file with mode: 0644]
queue-3.18/ipv6-pointer-math-error-in-ip6_tnl_parse_tlv_enc_lim.patch [new file with mode: 0644]
queue-3.18/ipv6-tcp-add-a-missing-tcp_v6_restore_cb.patch [new file with mode: 0644]
queue-3.18/l2tp-do-not-use-udp_ioctl.patch [new file with mode: 0644]
queue-3.18/mlx4-invoke-softirqs-after-napi_reschedule.patch [new file with mode: 0644]
queue-3.18/net-use-a-work-queue-to-defer-net_disable_timestamp-work.patch [new file with mode: 0644]
queue-3.18/netlabel-out-of-bound-access-in-cipso_v4_validate.patch [new file with mode: 0644]
queue-3.18/ping-fix-a-null-pointer-dereference.patch [new file with mode: 0644]
queue-3.18/sctp-avoid-bug_on-on-sctp_wait_for_sndbuf.patch [new file with mode: 0644]
queue-3.18/series [new file with mode: 0644]
queue-3.18/sit-fix-a-double-free-on-error-path.patch [new file with mode: 0644]
queue-3.18/tcp-avoid-infinite-loop-in-tcp_splice_read.patch [new file with mode: 0644]
queue-3.18/tcp-fix-0-divide-in-__tcp_select_window.patch [new file with mode: 0644]

diff --git a/queue-3.18/can-fix-kernel-panic-at-security_sock_rcv_skb.patch b/queue-3.18/can-fix-kernel-panic-at-security_sock_rcv_skb.patch
new file mode 100644 (file)
index 0000000..c035ec6
--- /dev/null
@@ -0,0 +1,205 @@
+From foo@baz Mon Feb 20 15:15:52 CET 2017
+From: Eric Dumazet <edumazet@google.com>
+Date: Fri, 27 Jan 2017 08:11:44 -0800
+Subject: can: Fix kernel panic at security_sock_rcv_skb
+
+From: Eric Dumazet <edumazet@google.com>
+
+
+[ Upstream commit f1712c73714088a7252d276a57126d56c7d37e64 ]
+
+Zhang Yanmin reported crashes [1] and provided a patch adding a
+synchronize_rcu() call in can_rx_unregister()
+
+The main problem seems that the sockets themselves are not RCU
+protected.
+
+If CAN uses RCU for delivery, then sockets should be freed only after
+one RCU grace period.
+
+Recent kernels could use sock_set_flag(sk, SOCK_RCU_FREE), but let's
+ease stable backports with the following fix instead.
+
+[1]
+BUG: unable to handle kernel NULL pointer dereference at (null)
+IP: [<ffffffff81495e25>] selinux_socket_sock_rcv_skb+0x65/0x2a0
+
+Call Trace:
+ <IRQ>
+ [<ffffffff81485d8c>] security_sock_rcv_skb+0x4c/0x60
+ [<ffffffff81d55771>] sk_filter+0x41/0x210
+ [<ffffffff81d12913>] sock_queue_rcv_skb+0x53/0x3a0
+ [<ffffffff81f0a2b3>] raw_rcv+0x2a3/0x3c0
+ [<ffffffff81f06eab>] can_rcv_filter+0x12b/0x370
+ [<ffffffff81f07af9>] can_receive+0xd9/0x120
+ [<ffffffff81f07beb>] can_rcv+0xab/0x100
+ [<ffffffff81d362ac>] __netif_receive_skb_core+0xd8c/0x11f0
+ [<ffffffff81d36734>] __netif_receive_skb+0x24/0xb0
+ [<ffffffff81d37f67>] process_backlog+0x127/0x280
+ [<ffffffff81d36f7b>] net_rx_action+0x33b/0x4f0
+ [<ffffffff810c88d4>] __do_softirq+0x184/0x440
+ [<ffffffff81f9e86c>] do_softirq_own_stack+0x1c/0x30
+ <EOI>
+ [<ffffffff810c76fb>] do_softirq.part.18+0x3b/0x40
+ [<ffffffff810c8bed>] do_softirq+0x1d/0x20
+ [<ffffffff81d30085>] netif_rx_ni+0xe5/0x110
+ [<ffffffff8199cc87>] slcan_receive_buf+0x507/0x520
+ [<ffffffff8167ef7c>] flush_to_ldisc+0x21c/0x230
+ [<ffffffff810e3baf>] process_one_work+0x24f/0x670
+ [<ffffffff810e44ed>] worker_thread+0x9d/0x6f0
+ [<ffffffff810e4450>] ? rescuer_thread+0x480/0x480
+ [<ffffffff810ebafc>] kthread+0x12c/0x150
+ [<ffffffff81f9ccef>] ret_from_fork+0x3f/0x70
+
+Reported-by: Zhang Yanmin <yanmin.zhang@intel.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/can/core.h |    7 +++----
+ net/can/af_can.c         |   12 ++++++++++--
+ net/can/af_can.h         |    3 ++-
+ net/can/bcm.c            |    4 ++--
+ net/can/gw.c             |    2 +-
+ net/can/raw.c            |    4 ++--
+ 6 files changed, 20 insertions(+), 12 deletions(-)
+
+--- a/include/linux/can/core.h
++++ b/include/linux/can/core.h
+@@ -45,10 +45,9 @@ struct can_proto {
+ extern int  can_proto_register(const struct can_proto *cp);
+ extern void can_proto_unregister(const struct can_proto *cp);
+-extern int  can_rx_register(struct net_device *dev, canid_t can_id,
+-                          canid_t mask,
+-                          void (*func)(struct sk_buff *, void *),
+-                          void *data, char *ident);
++int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
++                  void (*func)(struct sk_buff *, void *),
++                  void *data, char *ident, struct sock *sk);
+ extern void can_rx_unregister(struct net_device *dev, canid_t can_id,
+                             canid_t mask,
+--- a/net/can/af_can.c
++++ b/net/can/af_can.c
+@@ -446,6 +446,7 @@ static struct hlist_head *find_rcv_list(
+  * @func: callback function on filter match
+  * @data: returned parameter for callback function
+  * @ident: string for calling module identification
++ * @sk: socket pointer (might be NULL)
+  *
+  * Description:
+  *  Invokes the callback function with the received sk_buff and the given
+@@ -469,7 +470,7 @@ static struct hlist_head *find_rcv_list(
+  */
+ int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
+                   void (*func)(struct sk_buff *, void *), void *data,
+-                  char *ident)
++                  char *ident, struct sock *sk)
+ {
+       struct receiver *r;
+       struct hlist_head *rl;
+@@ -497,6 +498,7 @@ int can_rx_register(struct net_device *d
+               r->func    = func;
+               r->data    = data;
+               r->ident   = ident;
++              r->sk      = sk;
+               hlist_add_head_rcu(&r->list, rl);
+               d->entries++;
+@@ -521,8 +523,11 @@ EXPORT_SYMBOL(can_rx_register);
+ static void can_rx_delete_receiver(struct rcu_head *rp)
+ {
+       struct receiver *r = container_of(rp, struct receiver, rcu);
++      struct sock *sk = r->sk;
+       kmem_cache_free(rcv_cache, r);
++      if (sk)
++              sock_put(sk);
+ }
+ /**
+@@ -597,8 +602,11 @@ void can_rx_unregister(struct net_device
+       spin_unlock(&can_rcvlists_lock);
+       /* schedule the receiver item for deletion */
+-      if (r)
++      if (r) {
++              if (r->sk)
++                      sock_hold(r->sk);
+               call_rcu(&r->rcu, can_rx_delete_receiver);
++      }
+ }
+ EXPORT_SYMBOL(can_rx_unregister);
+--- a/net/can/af_can.h
++++ b/net/can/af_can.h
+@@ -50,13 +50,14 @@
+ struct receiver {
+       struct hlist_node list;
+-      struct rcu_head rcu;
+       canid_t can_id;
+       canid_t mask;
+       unsigned long matches;
+       void (*func)(struct sk_buff *, void *);
+       void *data;
+       char *ident;
++      struct sock *sk;
++      struct rcu_head rcu;
+ };
+ #define CAN_SFF_RCV_ARRAY_SZ (1 << CAN_SFF_ID_BITS)
+--- a/net/can/bcm.c
++++ b/net/can/bcm.c
+@@ -1169,7 +1169,7 @@ static int bcm_rx_setup(struct bcm_msg_h
+                               err = can_rx_register(dev, op->can_id,
+                                                     REGMASK(op->can_id),
+                                                     bcm_rx_handler, op,
+-                                                    "bcm");
++                                                    "bcm", sk);
+                               op->rx_reg_dev = dev;
+                               dev_put(dev);
+@@ -1178,7 +1178,7 @@ static int bcm_rx_setup(struct bcm_msg_h
+               } else
+                       err = can_rx_register(NULL, op->can_id,
+                                             REGMASK(op->can_id),
+-                                            bcm_rx_handler, op, "bcm");
++                                            bcm_rx_handler, op, "bcm", sk);
+               if (err) {
+                       /* this bcm rx op is broken -> remove it */
+                       list_del(&op->list);
+--- a/net/can/gw.c
++++ b/net/can/gw.c
+@@ -441,7 +441,7 @@ static inline int cgw_register_filter(st
+ {
+       return can_rx_register(gwj->src.dev, gwj->ccgw.filter.can_id,
+                              gwj->ccgw.filter.can_mask, can_can_gw_rcv,
+-                             gwj, "gw");
++                             gwj, "gw", NULL);
+ }
+ static inline void cgw_unregister_filter(struct cgw_job *gwj)
+--- a/net/can/raw.c
++++ b/net/can/raw.c
+@@ -164,7 +164,7 @@ static int raw_enable_filters(struct net
+       for (i = 0; i < count; i++) {
+               err = can_rx_register(dev, filter[i].can_id,
+                                     filter[i].can_mask,
+-                                    raw_rcv, sk, "raw");
++                                    raw_rcv, sk, "raw", sk);
+               if (err) {
+                       /* clean up successfully registered filters */
+                       while (--i >= 0)
+@@ -185,7 +185,7 @@ static int raw_enable_errfilter(struct n
+       if (err_mask)
+               err = can_rx_register(dev, 0, err_mask | CAN_ERR_FLAG,
+-                                    raw_rcv, sk, "raw");
++                                    raw_rcv, sk, "raw", sk);
+       return err;
+ }
diff --git a/queue-3.18/ip6_gre-fix-ip6gre_err-invalid-reads.patch b/queue-3.18/ip6_gre-fix-ip6gre_err-invalid-reads.patch
new file mode 100644 (file)
index 0000000..732e70e
--- /dev/null
@@ -0,0 +1,101 @@
+From foo@baz Mon Feb 20 15:15:52 CET 2017
+From: Eric Dumazet <edumazet@google.com>
+Date: Sat, 4 Feb 2017 23:18:55 -0800
+Subject: ip6_gre: fix ip6gre_err() invalid reads
+
+From: Eric Dumazet <edumazet@google.com>
+
+
+[ Upstream commit 7892032cfe67f4bde6fc2ee967e45a8fbaf33756 ]
+
+Andrey Konovalov reported out of bound accesses in ip6gre_err()
+
+If GRE flags contains GRE_KEY, the following expression
+*(((__be32 *)p) + (grehlen / 4) - 1)
+
+accesses data ~40 bytes after the expected point, since
+grehlen includes the size of IPv6 headers.
+
+Let's use a "struct gre_base_hdr *greh" pointer to make this
+code more readable.
+
+p[1] becomes greh->protocol.
+grhlen is the GRE header length.
+
+Fixes: c12b395a4664 ("gre: Support GRE over IPv6")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/ip6_gre.c |   41 ++++++++++++++++++++++-------------------
+ 1 file changed, 22 insertions(+), 19 deletions(-)
+
+--- a/net/ipv6/ip6_gre.c
++++ b/net/ipv6/ip6_gre.c
+@@ -55,6 +55,7 @@
+ #include <net/ip6_fib.h>
+ #include <net/ip6_route.h>
+ #include <net/ip6_tunnel.h>
++#include <net/gre.h>
+ static bool log_ecn_error = true;
+@@ -367,35 +368,37 @@ static void ip6gre_tunnel_uninit(struct
+ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+-              u8 type, u8 code, int offset, __be32 info)
++                     u8 type, u8 code, int offset, __be32 info)
+ {
+-      const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)skb->data;
+-      __be16 *p = (__be16 *)(skb->data + offset);
+-      int grehlen = offset + 4;
++      const struct gre_base_hdr *greh;
++      const struct ipv6hdr *ipv6h;
++      int grehlen = sizeof(*greh);
+       struct ip6_tnl *t;
++      int key_off = 0;
+       __be16 flags;
++      __be32 key;
+-      flags = p[0];
+-      if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) {
+-              if (flags&(GRE_VERSION|GRE_ROUTING))
+-                      return;
+-              if (flags&GRE_KEY) {
+-                      grehlen += 4;
+-                      if (flags&GRE_CSUM)
+-                              grehlen += 4;
+-              }
++      if (!pskb_may_pull(skb, offset + grehlen))
++              return;
++      greh = (const struct gre_base_hdr *)(skb->data + offset);
++      flags = greh->flags;
++      if (flags & (GRE_VERSION | GRE_ROUTING))
++              return;
++      if (flags & GRE_CSUM)
++              grehlen += 4;
++      if (flags & GRE_KEY) {
++              key_off = grehlen + offset;
++              grehlen += 4;
+       }
+-      /* If only 8 bytes returned, keyed message will be dropped here */
+-      if (!pskb_may_pull(skb, grehlen))
++      if (!pskb_may_pull(skb, offset + grehlen))
+               return;
+       ipv6h = (const struct ipv6hdr *)skb->data;
+-      p = (__be16 *)(skb->data + offset);
++      greh = (const struct gre_base_hdr *)(skb->data + offset);
++      key = key_off ? *(__be32 *)(skb->data + key_off) : 0;
+       t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr,
+-                              flags & GRE_KEY ?
+-                              *(((__be32 *)p) + (grehlen / 4) - 1) : 0,
+-                              p[1]);
++                               key, greh->protocol);
+       if (t == NULL)
+               return;
diff --git a/queue-3.18/ipv4-keep-skb-dst-around-in-presence-of-ip-options.patch b/queue-3.18/ipv4-keep-skb-dst-around-in-presence-of-ip-options.patch
new file mode 100644 (file)
index 0000000..e75f0b7
--- /dev/null
@@ -0,0 +1,49 @@
+From foo@baz Mon Feb 20 15:15:52 CET 2017
+From: Eric Dumazet <edumazet@google.com>
+Date: Sat, 4 Feb 2017 11:16:52 -0800
+Subject: ipv4: keep skb->dst around in presence of IP options
+
+From: Eric Dumazet <edumazet@google.com>
+
+
+[ Upstream commit 34b2cef20f19c87999fff3da4071e66937db9644 ]
+
+Andrey Konovalov got crashes in __ip_options_echo() when a NULL skb->dst
+is accessed.
+
+ipv4_pktinfo_prepare() should not drop the dst if (evil) IP options
+are present.
+
+We could refine the test to the presence of ts_needtime or srr,
+but IP options are not often used, so let's be conservative.
+
+Thanks to syzkaller team for finding this bug.
+
+Fixes: d826eb14ecef ("ipv4: PKTINFO doesnt need dst reference")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/ip_sockglue.c |    9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/net/ipv4/ip_sockglue.c
++++ b/net/ipv4/ip_sockglue.c
+@@ -1066,7 +1066,14 @@ void ipv4_pktinfo_prepare(const struct s
+               pktinfo->ipi_ifindex = 0;
+               pktinfo->ipi_spec_dst.s_addr = 0;
+       }
+-      skb_dst_drop(skb);
++      /* We need to keep the dst for __ip_options_echo()
++       * We could restrict the test to opt.ts_needtime || opt.srr,
++       * but the following is good enough as IP options are not often used.
++       */
++      if (unlikely(IPCB(skb)->opt.optlen))
++              skb_dst_force(skb);
++      else
++              skb_dst_drop(skb);
+ }
+ int ip_setsockopt(struct sock *sk, int level,
diff --git a/queue-3.18/ipv6-fix-ip6_tnl_parse_tlv_enc_lim.patch b/queue-3.18/ipv6-fix-ip6_tnl_parse_tlv_enc_lim.patch
new file mode 100644 (file)
index 0000000..2c1aa99
--- /dev/null
@@ -0,0 +1,103 @@
+From foo@baz Mon Feb 20 15:15:52 CET 2017
+From: Eric Dumazet <edumazet@google.com>
+Date: Mon, 23 Jan 2017 16:43:06 -0800
+Subject: ipv6: fix ip6_tnl_parse_tlv_enc_lim()
+
+From: Eric Dumazet <edumazet@google.com>
+
+
+[ Upstream commit fbfa743a9d2a0ffa24251764f10afc13eb21e739 ]
+
+This function suffers from multiple issues.
+
+First one is that pskb_may_pull() may reallocate skb->head,
+so the 'raw' pointer needs either to be reloaded or not used at all.
+
+Second issue is that NEXTHDR_DEST handling does not validate
+that the options are present in skb->data, so we might read
+garbage or access non existent memory.
+
+With help from Willem de Bruijn.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: Dmitry Vyukov  <dvyukov@google.com>
+Cc: Willem de Bruijn <willemb@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/ip6_tunnel.c |   34 ++++++++++++++++++++++------------
+ 1 file changed, 22 insertions(+), 12 deletions(-)
+
+--- a/net/ipv6/ip6_tunnel.c
++++ b/net/ipv6/ip6_tunnel.c
+@@ -407,18 +407,19 @@ ip6_tnl_dev_uninit(struct net_device *de
+ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw)
+ {
+-      const struct ipv6hdr *ipv6h = (const struct ipv6hdr *) raw;
+-      __u8 nexthdr = ipv6h->nexthdr;
+-      __u16 off = sizeof(*ipv6h);
++      const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)raw;
++      unsigned int nhoff = raw - skb->data;
++      unsigned int off = nhoff + sizeof(*ipv6h);
++      u8 next, nexthdr = ipv6h->nexthdr;
+       while (ipv6_ext_hdr(nexthdr) && nexthdr != NEXTHDR_NONE) {
+-              __u16 optlen = 0;
+               struct ipv6_opt_hdr *hdr;
+-              if (raw + off + sizeof(*hdr) > skb->data &&
+-                  !pskb_may_pull(skb, raw - skb->data + off + sizeof (*hdr)))
++              u16 optlen;
++
++              if (!pskb_may_pull(skb, off + sizeof(*hdr)))
+                       break;
+-              hdr = (struct ipv6_opt_hdr *) (raw + off);
++              hdr = (struct ipv6_opt_hdr *)(skb->data + off);
+               if (nexthdr == NEXTHDR_FRAGMENT) {
+                       struct frag_hdr *frag_hdr = (struct frag_hdr *) hdr;
+                       if (frag_hdr->frag_off)
+@@ -429,20 +430,29 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct s
+               } else {
+                       optlen = ipv6_optlen(hdr);
+               }
++              /* cache hdr->nexthdr, since pskb_may_pull() might
++               * invalidate hdr
++               */
++              next = hdr->nexthdr;
+               if (nexthdr == NEXTHDR_DEST) {
+-                      __u16 i = off + 2;
++                      u16 i = 2;
++
++                      /* Remember : hdr is no longer valid at this point. */
++                      if (!pskb_may_pull(skb, off + optlen))
++                              break;
++
+                       while (1) {
+                               struct ipv6_tlv_tnl_enc_lim *tel;
+                               /* No more room for encapsulation limit */
+-                              if (i + sizeof (*tel) > off + optlen)
++                              if (i + sizeof(*tel) > optlen)
+                                       break;
+-                              tel = (struct ipv6_tlv_tnl_enc_lim *) &raw[i];
++                              tel = (struct ipv6_tlv_tnl_enc_lim *) skb->data + off + i;
+                               /* return index of option if found and valid */
+                               if (tel->type == IPV6_TLV_TNL_ENCAP_LIMIT &&
+                                   tel->length == 1)
+-                                      return i;
++                                      return i + off - nhoff;
+                               /* else jump to next option */
+                               if (tel->type)
+                                       i += tel->length + 2;
+@@ -450,7 +460,7 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct s
+                                       i++;
+                       }
+               }
+-              nexthdr = hdr->nexthdr;
++              nexthdr = next;
+               off += optlen;
+       }
+       return 0;
diff --git a/queue-3.18/ipv6-pointer-math-error-in-ip6_tnl_parse_tlv_enc_lim.patch b/queue-3.18/ipv6-pointer-math-error-in-ip6_tnl_parse_tlv_enc_lim.patch
new file mode 100644 (file)
index 0000000..c1c3885
--- /dev/null
@@ -0,0 +1,34 @@
+From foo@baz Mon Feb 20 15:15:52 CET 2017
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Wed, 1 Feb 2017 11:46:32 +0300
+Subject: ipv6: pointer math error in ip6_tnl_parse_tlv_enc_lim()
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+
+[ Upstream commit 63117f09c768be05a0bf465911297dc76394f686 ]
+
+Casting is a high precedence operation but "off" and "i" are in terms of
+bytes so we need to have some parenthesis here.
+
+Fixes: fbfa743a9d2a ("ipv6: fix ip6_tnl_parse_tlv_enc_lim()")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Acked-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/ip6_tunnel.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/ipv6/ip6_tunnel.c
++++ b/net/ipv6/ip6_tunnel.c
+@@ -448,7 +448,7 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct s
+                               if (i + sizeof(*tel) > optlen)
+                                       break;
+-                              tel = (struct ipv6_tlv_tnl_enc_lim *) skb->data + off + i;
++                              tel = (struct ipv6_tlv_tnl_enc_lim *)(skb->data + off + i);
+                               /* return index of option if found and valid */
+                               if (tel->type == IPV6_TLV_TNL_ENCAP_LIMIT &&
+                                   tel->length == 1)
diff --git a/queue-3.18/ipv6-tcp-add-a-missing-tcp_v6_restore_cb.patch b/queue-3.18/ipv6-tcp-add-a-missing-tcp_v6_restore_cb.patch
new file mode 100644 (file)
index 0000000..2325a54
--- /dev/null
@@ -0,0 +1,73 @@
+From foo@baz Mon Feb 20 15:15:52 CET 2017
+From: Eric Dumazet <edumazet@google.com>
+Date: Sun, 5 Feb 2017 20:23:22 -0800
+Subject: ipv6: tcp: add a missing tcp_v6_restore_cb()
+
+From: Eric Dumazet <edumazet@google.com>
+
+
+[ Upstream commit ebf6c9cb23d7e56eec8575a88071dec97ad5c6e2 ]
+
+Dmitry reported use-after-free in ip6_datagram_recv_specific_ctl()
+
+A similar bug was fixed in commit 8ce48623f0cf ("ipv6: tcp: restore
+IP6CB for pktoptions skbs"), but I missed another spot.
+
+tcp_v6_syn_recv_sock() can indeed set np->pktoptions from ireq->pktopts
+
+Fixes: 971f10eca186 ("tcp: better TCP_SKB_CB layout to reduce cache line misses")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/tcp_ipv6.c |   22 ++++++++++++----------
+ 1 file changed, 12 insertions(+), 10 deletions(-)
+
+--- a/net/ipv6/tcp_ipv6.c
++++ b/net/ipv6/tcp_ipv6.c
+@@ -1049,6 +1049,15 @@ drop:
+       return 0; /* don't send reset */
+ }
++static void tcp_v6_restore_cb(struct sk_buff *skb)
++{
++      /* We need to move header back to the beginning if xfrm6_policy_check()
++       * and tcp_v6_fill_cb() are going to be called again.
++       */
++      memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6,
++              sizeof(struct inet6_skb_parm));
++}
++
+ static struct sock *tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
+                                        struct request_sock *req,
+                                        struct dst_entry *dst)
+@@ -1180,8 +1189,10 @@ static struct sock *tcp_v6_syn_recv_sock
+                                             sk_gfp_atomic(sk, GFP_ATOMIC));
+               consume_skb(ireq->pktopts);
+               ireq->pktopts = NULL;
+-              if (newnp->pktoptions)
++              if (newnp->pktoptions) {
++                      tcp_v6_restore_cb(newnp->pktoptions);
+                       skb_set_owner_r(newnp->pktoptions, newsk);
++              }
+       }
+       newnp->opt        = NULL;
+       newnp->mcast_oif  = tcp_v6_iif(skb);
+@@ -1414,15 +1425,6 @@ static void tcp_v6_fill_cb(struct sk_buf
+       TCP_SKB_CB(skb)->sacked = 0;
+ }
+-static void tcp_v6_restore_cb(struct sk_buff *skb)
+-{
+-      /* We need to move header back to the beginning if xfrm6_policy_check()
+-       * and tcp_v6_fill_cb() are going to be called again.
+-       */
+-      memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6,
+-              sizeof(struct inet6_skb_parm));
+-}
+-
+ static int tcp_v6_rcv(struct sk_buff *skb)
+ {
+       const struct tcphdr *th;
diff --git a/queue-3.18/l2tp-do-not-use-udp_ioctl.patch b/queue-3.18/l2tp-do-not-use-udp_ioctl.patch
new file mode 100644 (file)
index 0000000..b230607
--- /dev/null
@@ -0,0 +1,110 @@
+From foo@baz Mon Feb 20 15:15:52 CET 2017
+From: Eric Dumazet <edumazet@google.com>
+Date: Thu, 9 Feb 2017 16:15:52 -0800
+Subject: l2tp: do not use udp_ioctl()
+
+From: Eric Dumazet <edumazet@google.com>
+
+
+[ Upstream commit 72fb96e7bdbbdd4421b0726992496531060f3636 ]
+
+udp_ioctl(), as its name suggests, is used by UDP protocols,
+but is also used by L2TP :(
+
+L2TP should use its own handler, because it really does not
+look the same.
+
+SIOCINQ for instance should not assume UDP checksum or headers.
+
+Thanks to Andrey and syzkaller team for providing the report
+and a nice reproducer.
+
+While crashes only happen on recent kernels (after commit
+7c13f97ffde6 ("udp: do fwd memory scheduling on dequeue")), this
+probably needs to be backported to older kernels.
+
+Fixes: 7c13f97ffde6 ("udp: do fwd memory scheduling on dequeue")
+Fixes: 85584672012e ("udp: Fix udp_poll() and ioctl()")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Acked-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/l2tp/l2tp_core.h |    1 +
+ net/l2tp/l2tp_ip.c   |   27 ++++++++++++++++++++++++++-
+ net/l2tp/l2tp_ip6.c  |    2 +-
+ 3 files changed, 28 insertions(+), 2 deletions(-)
+
+--- a/net/l2tp/l2tp_core.h
++++ b/net/l2tp/l2tp_core.h
+@@ -273,6 +273,7 @@ int l2tp_xmit_skb(struct l2tp_session *s
+ int l2tp_nl_register_ops(enum l2tp_pwtype pw_type,
+                        const struct l2tp_nl_cmd_ops *ops);
+ void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type);
++int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg);
+ /* Session reference counts. Incremented when code obtains a reference
+  * to a session.
+--- a/net/l2tp/l2tp_ip.c
++++ b/net/l2tp/l2tp_ip.c
+@@ -11,6 +11,7 @@
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
++#include <asm/ioctls.h>
+ #include <linux/icmp.h>
+ #include <linux/module.h>
+ #include <linux/skbuff.h>
+@@ -554,6 +555,30 @@ out:
+       return err ? err : copied;
+ }
++int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg)
++{
++      struct sk_buff *skb;
++      int amount;
++
++      switch (cmd) {
++      case SIOCOUTQ:
++              amount = sk_wmem_alloc_get(sk);
++              break;
++      case SIOCINQ:
++              spin_lock_bh(&sk->sk_receive_queue.lock);
++              skb = skb_peek(&sk->sk_receive_queue);
++              amount = skb ? skb->len : 0;
++              spin_unlock_bh(&sk->sk_receive_queue.lock);
++              break;
++
++      default:
++              return -ENOIOCTLCMD;
++      }
++
++      return put_user(amount, (int __user *)arg);
++}
++EXPORT_SYMBOL(l2tp_ioctl);
++
+ static struct proto l2tp_ip_prot = {
+       .name              = "L2TP/IP",
+       .owner             = THIS_MODULE,
+@@ -562,7 +587,7 @@ static struct proto l2tp_ip_prot = {
+       .bind              = l2tp_ip_bind,
+       .connect           = l2tp_ip_connect,
+       .disconnect        = l2tp_ip_disconnect,
+-      .ioctl             = udp_ioctl,
++      .ioctl             = l2tp_ioctl,
+       .destroy           = l2tp_ip_destroy_sock,
+       .setsockopt        = ip_setsockopt,
+       .getsockopt        = ip_getsockopt,
+--- a/net/l2tp/l2tp_ip6.c
++++ b/net/l2tp/l2tp_ip6.c
+@@ -715,7 +715,7 @@ static struct proto l2tp_ip6_prot = {
+       .bind              = l2tp_ip6_bind,
+       .connect           = l2tp_ip6_connect,
+       .disconnect        = l2tp_ip6_disconnect,
+-      .ioctl             = udp_ioctl,
++      .ioctl             = l2tp_ioctl,
+       .destroy           = l2tp_ip6_destroy_sock,
+       .setsockopt        = ipv6_setsockopt,
+       .getsockopt        = ipv6_getsockopt,
diff --git a/queue-3.18/mlx4-invoke-softirqs-after-napi_reschedule.patch b/queue-3.18/mlx4-invoke-softirqs-after-napi_reschedule.patch
new file mode 100644 (file)
index 0000000..16d65b3
--- /dev/null
@@ -0,0 +1,45 @@
+From foo@baz Mon Feb 20 15:15:52 CET 2017
+From: Benjamin Poirier <bpoirier@suse.com>
+Date: Mon, 6 Feb 2017 10:14:31 -0800
+Subject: mlx4: Invoke softirqs after napi_reschedule
+
+From: Benjamin Poirier <bpoirier@suse.com>
+
+
+[ Upstream commit bd4ce941c8d5b862b2f83364be5dbe8fc8ab48f8 ]
+
+mlx4 may schedule napi from a workqueue. Afterwards, softirqs are not run
+in a deterministic time frame and the following message may be logged:
+NOHZ: local_softirq_pending 08
+
+The problem is the same as what was described in commit ec13ee80145c
+("virtio_net: invoke softirqs after __napi_schedule") and this patch
+applies the same fix to mlx4.
+
+Fixes: 07841f9d94c1 ("net/mlx4_en: Schedule napi when RX buffers allocation fails")
+Cc: Eric Dumazet <eric.dumazet@gmail.com>
+Signed-off-by: Benjamin Poirier <bpoirier@suse.com>
+Acked-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Tariq Toukan <tariqt@mellanox.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/mellanox/mlx4/en_rx.c |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+@@ -501,8 +501,11 @@ void mlx4_en_recover_from_oom(struct mlx
+               return;
+       for (ring = 0; ring < priv->rx_ring_num; ring++) {
+-              if (mlx4_en_is_ring_empty(priv->rx_ring[ring]))
++              if (mlx4_en_is_ring_empty(priv->rx_ring[ring])) {
++                      local_bh_disable();
+                       napi_reschedule(&priv->rx_cq[ring]->napi);
++                      local_bh_enable();
++              }
+       }
+ }
diff --git a/queue-3.18/net-use-a-work-queue-to-defer-net_disable_timestamp-work.patch b/queue-3.18/net-use-a-work-queue-to-defer-net_disable_timestamp-work.patch
new file mode 100644 (file)
index 0000000..a83f203
--- /dev/null
@@ -0,0 +1,219 @@
+From foo@baz Mon Feb 20 15:15:52 CET 2017
+From: Eric Dumazet <edumazet@google.com>
+Date: Thu, 2 Feb 2017 10:31:35 -0800
+Subject: net: use a work queue to defer net_disable_timestamp() work
+
+From: Eric Dumazet <edumazet@google.com>
+
+
+[ Upstream commit 5fa8bbda38c668e56b0c6cdecced2eac2fe36dec ]
+
+Dmitry reported a warning [1] showing that we were calling
+net_disable_timestamp() -> static_key_slow_dec() from a non
+process context.
+
+Grabbing a mutex while holding a spinlock or rcu_read_lock()
+is not allowed.
+
+As Cong suggested, we now use a work queue.
+
+It is possible netstamp_clear() exits while netstamp_needed_deferred
+is not zero, but it is probably not worth trying to do better than that.
+
+netstamp_needed_deferred atomic tracks the exact number of deferred
+decrements.
+
+[1]
+[ INFO: suspicious RCU usage. ]
+4.10.0-rc5+ #192 Not tainted
+-------------------------------
+./include/linux/rcupdate.h:561 Illegal context switch in RCU read-side
+critical section!
+
+other info that might help us debug this:
+
+rcu_scheduler_active = 2, debug_locks = 0
+2 locks held by syz-executor14/23111:
+ #0:  (sk_lock-AF_INET6){+.+.+.}, at: [<ffffffff83a35c35>] lock_sock
+include/net/sock.h:1454 [inline]
+ #0:  (sk_lock-AF_INET6){+.+.+.}, at: [<ffffffff83a35c35>]
+rawv6_sendmsg+0x1e65/0x3ec0 net/ipv6/raw.c:919
+ #1:  (rcu_read_lock){......}, at: [<ffffffff83ae2678>] nf_hook
+include/linux/netfilter.h:201 [inline]
+ #1:  (rcu_read_lock){......}, at: [<ffffffff83ae2678>]
+__ip6_local_out+0x258/0x840 net/ipv6/output_core.c:160
+
+stack backtrace:
+CPU: 2 PID: 23111 Comm: syz-executor14 Not tainted 4.10.0-rc5+ #192
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs
+01/01/2011
+Call Trace:
+ __dump_stack lib/dump_stack.c:15 [inline]
+ dump_stack+0x2ee/0x3ef lib/dump_stack.c:51
+ lockdep_rcu_suspicious+0x139/0x180 kernel/locking/lockdep.c:4452
+ rcu_preempt_sleep_check include/linux/rcupdate.h:560 [inline]
+ ___might_sleep+0x560/0x650 kernel/sched/core.c:7748
+ __might_sleep+0x95/0x1a0 kernel/sched/core.c:7739
+ mutex_lock_nested+0x24f/0x1730 kernel/locking/mutex.c:752
+ atomic_dec_and_mutex_lock+0x119/0x160 kernel/locking/mutex.c:1060
+ __static_key_slow_dec+0x7a/0x1e0 kernel/jump_label.c:149
+ static_key_slow_dec+0x51/0x90 kernel/jump_label.c:174
+ net_disable_timestamp+0x3b/0x50 net/core/dev.c:1728
+ sock_disable_timestamp+0x98/0xc0 net/core/sock.c:403
+ __sk_destruct+0x27d/0x6b0 net/core/sock.c:1441
+ sk_destruct+0x47/0x80 net/core/sock.c:1460
+ __sk_free+0x57/0x230 net/core/sock.c:1468
+ sock_wfree+0xae/0x120 net/core/sock.c:1645
+ skb_release_head_state+0xfc/0x200 net/core/skbuff.c:655
+ skb_release_all+0x15/0x60 net/core/skbuff.c:668
+ __kfree_skb+0x15/0x20 net/core/skbuff.c:684
+ kfree_skb+0x16e/0x4c0 net/core/skbuff.c:705
+ inet_frag_destroy+0x121/0x290 net/ipv4/inet_fragment.c:304
+ inet_frag_put include/net/inet_frag.h:133 [inline]
+ nf_ct_frag6_gather+0x1106/0x3840
+net/ipv6/netfilter/nf_conntrack_reasm.c:617
+ ipv6_defrag+0x1be/0x2b0 net/ipv6/netfilter/nf_defrag_ipv6_hooks.c:68
+ nf_hook_entry_hookfn include/linux/netfilter.h:102 [inline]
+ nf_hook_slow+0xc3/0x290 net/netfilter/core.c:310
+ nf_hook include/linux/netfilter.h:212 [inline]
+ __ip6_local_out+0x489/0x840 net/ipv6/output_core.c:160
+ ip6_local_out+0x2d/0x170 net/ipv6/output_core.c:170
+ ip6_send_skb+0xa1/0x340 net/ipv6/ip6_output.c:1722
+ ip6_push_pending_frames+0xb3/0xe0 net/ipv6/ip6_output.c:1742
+ rawv6_push_pending_frames net/ipv6/raw.c:613 [inline]
+ rawv6_sendmsg+0x2d1a/0x3ec0 net/ipv6/raw.c:927
+ inet_sendmsg+0x164/0x5b0 net/ipv4/af_inet.c:744
+ sock_sendmsg_nosec net/socket.c:635 [inline]
+ sock_sendmsg+0xca/0x110 net/socket.c:645
+ sock_write_iter+0x326/0x600 net/socket.c:848
+ do_iter_readv_writev+0x2e3/0x5b0 fs/read_write.c:695
+ do_readv_writev+0x42c/0x9b0 fs/read_write.c:872
+ vfs_writev+0x87/0xc0 fs/read_write.c:911
+ do_writev+0x110/0x2c0 fs/read_write.c:944
+ SYSC_writev fs/read_write.c:1017 [inline]
+ SyS_writev+0x27/0x30 fs/read_write.c:1014
+ entry_SYSCALL_64_fastpath+0x1f/0xc2
+RIP: 0033:0x445559
+RSP: 002b:00007f6f46fceb58 EFLAGS: 00000292 ORIG_RAX: 0000000000000014
+RAX: ffffffffffffffda RBX: 0000000000000005 RCX: 0000000000445559
+RDX: 0000000000000001 RSI: 0000000020f1eff0 RDI: 0000000000000005
+RBP: 00000000006e19c0 R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000292 R12: 0000000000700000
+R13: 0000000020f59000 R14: 0000000000000015 R15: 0000000000020400
+BUG: sleeping function called from invalid context at
+kernel/locking/mutex.c:752
+in_atomic(): 1, irqs_disabled(): 0, pid: 23111, name: syz-executor14
+INFO: lockdep is turned off.
+CPU: 2 PID: 23111 Comm: syz-executor14 Not tainted 4.10.0-rc5+ #192
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs
+01/01/2011
+Call Trace:
+ __dump_stack lib/dump_stack.c:15 [inline]
+ dump_stack+0x2ee/0x3ef lib/dump_stack.c:51
+ ___might_sleep+0x47e/0x650 kernel/sched/core.c:7780
+ __might_sleep+0x95/0x1a0 kernel/sched/core.c:7739
+ mutex_lock_nested+0x24f/0x1730 kernel/locking/mutex.c:752
+ atomic_dec_and_mutex_lock+0x119/0x160 kernel/locking/mutex.c:1060
+ __static_key_slow_dec+0x7a/0x1e0 kernel/jump_label.c:149
+ static_key_slow_dec+0x51/0x90 kernel/jump_label.c:174
+ net_disable_timestamp+0x3b/0x50 net/core/dev.c:1728
+ sock_disable_timestamp+0x98/0xc0 net/core/sock.c:403
+ __sk_destruct+0x27d/0x6b0 net/core/sock.c:1441
+ sk_destruct+0x47/0x80 net/core/sock.c:1460
+ __sk_free+0x57/0x230 net/core/sock.c:1468
+ sock_wfree+0xae/0x120 net/core/sock.c:1645
+ skb_release_head_state+0xfc/0x200 net/core/skbuff.c:655
+ skb_release_all+0x15/0x60 net/core/skbuff.c:668
+ __kfree_skb+0x15/0x20 net/core/skbuff.c:684
+ kfree_skb+0x16e/0x4c0 net/core/skbuff.c:705
+ inet_frag_destroy+0x121/0x290 net/ipv4/inet_fragment.c:304
+ inet_frag_put include/net/inet_frag.h:133 [inline]
+ nf_ct_frag6_gather+0x1106/0x3840
+net/ipv6/netfilter/nf_conntrack_reasm.c:617
+ ipv6_defrag+0x1be/0x2b0 net/ipv6/netfilter/nf_defrag_ipv6_hooks.c:68
+ nf_hook_entry_hookfn include/linux/netfilter.h:102 [inline]
+ nf_hook_slow+0xc3/0x290 net/netfilter/core.c:310
+ nf_hook include/linux/netfilter.h:212 [inline]
+ __ip6_local_out+0x489/0x840 net/ipv6/output_core.c:160
+ ip6_local_out+0x2d/0x170 net/ipv6/output_core.c:170
+ ip6_send_skb+0xa1/0x340 net/ipv6/ip6_output.c:1722
+ ip6_push_pending_frames+0xb3/0xe0 net/ipv6/ip6_output.c:1742
+ rawv6_push_pending_frames net/ipv6/raw.c:613 [inline]
+ rawv6_sendmsg+0x2d1a/0x3ec0 net/ipv6/raw.c:927
+ inet_sendmsg+0x164/0x5b0 net/ipv4/af_inet.c:744
+ sock_sendmsg_nosec net/socket.c:635 [inline]
+ sock_sendmsg+0xca/0x110 net/socket.c:645
+ sock_write_iter+0x326/0x600 net/socket.c:848
+ do_iter_readv_writev+0x2e3/0x5b0 fs/read_write.c:695
+ do_readv_writev+0x42c/0x9b0 fs/read_write.c:872
+ vfs_writev+0x87/0xc0 fs/read_write.c:911
+ do_writev+0x110/0x2c0 fs/read_write.c:944
+ SYSC_writev fs/read_write.c:1017 [inline]
+ SyS_writev+0x27/0x30 fs/read_write.c:1014
+ entry_SYSCALL_64_fastpath+0x1f/0xc2
+RIP: 0033:0x445559
+
+Fixes: b90e5794c5bd ("net: dont call jump_label_dec from irq context")
+Suggested-by: Cong Wang <xiyou.wangcong@gmail.com>
+Reported-by: Dmitry Vyukov <dvyukov@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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/core/dev.c |   31 +++++++++++++------------------
+ 1 file changed, 13 insertions(+), 18 deletions(-)
+
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -1611,24 +1611,19 @@ EXPORT_SYMBOL(call_netdevice_notifiers);
+ static struct static_key netstamp_needed __read_mostly;
+ #ifdef HAVE_JUMP_LABEL
+-/* We are not allowed to call static_key_slow_dec() from irq context
+- * If net_disable_timestamp() is called from irq context, defer the
+- * static_key_slow_dec() calls.
+- */
+ static atomic_t netstamp_needed_deferred;
+-#endif
+-
+-void net_enable_timestamp(void)
++static void netstamp_clear(struct work_struct *work)
+ {
+-#ifdef HAVE_JUMP_LABEL
+       int deferred = atomic_xchg(&netstamp_needed_deferred, 0);
+-      if (deferred) {
+-              while (--deferred)
+-                      static_key_slow_dec(&netstamp_needed);
+-              return;
+-      }
++      while (deferred--)
++              static_key_slow_dec(&netstamp_needed);
++}
++static DECLARE_WORK(netstamp_work, netstamp_clear);
+ #endif
++
++void net_enable_timestamp(void)
++{
+       static_key_slow_inc(&netstamp_needed);
+ }
+ EXPORT_SYMBOL(net_enable_timestamp);
+@@ -1636,12 +1631,12 @@ EXPORT_SYMBOL(net_enable_timestamp);
+ void net_disable_timestamp(void)
+ {
+ #ifdef HAVE_JUMP_LABEL
+-      if (in_interrupt()) {
+-              atomic_inc(&netstamp_needed_deferred);
+-              return;
+-      }
+-#endif
++      /* net_disable_timestamp() can be called from non process context */
++      atomic_inc(&netstamp_needed_deferred);
++      schedule_work(&netstamp_work);
++#else
+       static_key_slow_dec(&netstamp_needed);
++#endif
+ }
+ EXPORT_SYMBOL(net_disable_timestamp);
diff --git a/queue-3.18/netlabel-out-of-bound-access-in-cipso_v4_validate.patch b/queue-3.18/netlabel-out-of-bound-access-in-cipso_v4_validate.patch
new file mode 100644 (file)
index 0000000..329813f
--- /dev/null
@@ -0,0 +1,53 @@
+From foo@baz Mon Feb 20 15:15:52 CET 2017
+From: Eric Dumazet <edumazet@google.com>
+Date: Fri, 3 Feb 2017 00:03:26 -0800
+Subject: netlabel: out of bound access in cipso_v4_validate()
+
+From: Eric Dumazet <edumazet@google.com>
+
+
+[ Upstream commit d71b7896886345c53ef1d84bda2bc758554f5d61 ]
+
+syzkaller found another out of bound access in ip_options_compile(),
+or more exactly in cipso_v4_validate()
+
+Fixes: 20e2a8648596 ("cipso: handle CIPSO options correctly when NetLabel is disabled")
+Fixes: 446fda4f2682 ("[NetLabel]: CIPSOv4 engine")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: Dmitry Vyukov  <dvyukov@google.com>
+Cc: Paul Moore <paul@paul-moore.com>
+Acked-by: Paul Moore <paul@paul-moore.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/cipso_ipv4.h |    4 ++++
+ net/ipv4/cipso_ipv4.c    |    4 ++++
+ 2 files changed, 8 insertions(+)
+
+--- a/include/net/cipso_ipv4.h
++++ b/include/net/cipso_ipv4.h
+@@ -309,6 +309,10 @@ static inline int cipso_v4_validate(cons
+       }
+       for (opt_iter = 6; opt_iter < opt_len;) {
++              if (opt_iter + 1 == opt_len) {
++                      err_offset = opt_iter;
++                      goto out;
++              }
+               tag_len = opt[opt_iter + 1];
+               if ((tag_len == 0) || (tag_len > (opt_len - opt_iter))) {
+                       err_offset = opt_iter + 1;
+--- a/net/ipv4/cipso_ipv4.c
++++ b/net/ipv4/cipso_ipv4.c
+@@ -1655,6 +1655,10 @@ int cipso_v4_validate(const struct sk_bu
+                               goto validate_return_locked;
+                       }
++              if (opt_iter + 1 == opt_len) {
++                      err_offset = opt_iter;
++                      goto validate_return_locked;
++              }
+               tag_len = tag[1];
+               if (tag_len > (opt_len - opt_iter)) {
+                       err_offset = opt_iter + 1;
diff --git a/queue-3.18/ping-fix-a-null-pointer-dereference.patch b/queue-3.18/ping-fix-a-null-pointer-dereference.patch
new file mode 100644 (file)
index 0000000..c716ff7
--- /dev/null
@@ -0,0 +1,63 @@
+From foo@baz Mon Feb 20 15:15:52 CET 2017
+From: WANG Cong <xiyou.wangcong@gmail.com>
+Date: Tue, 7 Feb 2017 12:59:46 -0800
+Subject: ping: fix a null pointer dereference
+
+From: WANG Cong <xiyou.wangcong@gmail.com>
+
+
+[ Upstream commit 73d2c6678e6c3af7e7a42b1e78cd0211782ade32 ]
+
+Andrey reported a kernel crash:
+
+  general protection fault: 0000 [#1] SMP KASAN
+  Dumping ftrace buffer:
+     (ftrace buffer empty)
+  Modules linked in:
+  CPU: 2 PID: 3880 Comm: syz-executor1 Not tainted 4.10.0-rc6+ #124
+  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
+  task: ffff880060048040 task.stack: ffff880069be8000
+  RIP: 0010:ping_v4_push_pending_frames net/ipv4/ping.c:647 [inline]
+  RIP: 0010:ping_v4_sendmsg+0x1acd/0x23f0 net/ipv4/ping.c:837
+  RSP: 0018:ffff880069bef8b8 EFLAGS: 00010206
+  RAX: dffffc0000000000 RBX: ffff880069befb90 RCX: 0000000000000000
+  RDX: 0000000000000018 RSI: ffff880069befa30 RDI: 00000000000000c2
+  RBP: ffff880069befbb8 R08: 0000000000000008 R09: 0000000000000000
+  R10: 0000000000000002 R11: 0000000000000000 R12: ffff880069befab0
+  R13: ffff88006c624a80 R14: ffff880069befa70 R15: 0000000000000000
+  FS:  00007f6f7c716700(0000) GS:ffff88006de00000(0000) knlGS:0000000000000000
+  CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+  CR2: 00000000004a6f28 CR3: 000000003a134000 CR4: 00000000000006e0
+  Call Trace:
+   inet_sendmsg+0x164/0x5b0 net/ipv4/af_inet.c:744
+   sock_sendmsg_nosec net/socket.c:635 [inline]
+   sock_sendmsg+0xca/0x110 net/socket.c:645
+   SYSC_sendto+0x660/0x810 net/socket.c:1687
+   SyS_sendto+0x40/0x50 net/socket.c:1655
+   entry_SYSCALL_64_fastpath+0x1f/0xc2
+
+This is because we miss a check for NULL pointer for skb_peek() when
+the queue is empty. Other places already have the same check.
+
+Fixes: c319b4d76b9e ("net: ipv4: add IPPROTO_ICMP socket kind")
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Tested-by: Andrey Konovalov <andreyknvl@google.com>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/ping.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/ipv4/ping.c
++++ b/net/ipv4/ping.c
+@@ -644,6 +644,8 @@ static int ping_v4_push_pending_frames(s
+ {
+       struct sk_buff *skb = skb_peek(&sk->sk_write_queue);
++      if (!skb)
++              return 0;
+       pfh->wcheck = csum_partial((char *)&pfh->icmph,
+               sizeof(struct icmphdr), pfh->wcheck);
+       pfh->icmph.checksum = csum_fold(pfh->wcheck);
diff --git a/queue-3.18/sctp-avoid-bug_on-on-sctp_wait_for_sndbuf.patch b/queue-3.18/sctp-avoid-bug_on-on-sctp_wait_for_sndbuf.patch
new file mode 100644 (file)
index 0000000..cd7f09a
--- /dev/null
@@ -0,0 +1,41 @@
+From foo@baz Mon Feb 20 15:15:52 CET 2017
+From: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Date: Mon, 6 Feb 2017 18:10:31 -0200
+Subject: sctp: avoid BUG_ON on sctp_wait_for_sndbuf
+
+From: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+
+
+[ Upstream commit 2dcab598484185dea7ec22219c76dcdd59e3cb90 ]
+
+Alexander Popov reported that an application may trigger a BUG_ON in
+sctp_wait_for_sndbuf if the socket tx buffer is full, a thread is
+waiting on it to queue more data and meanwhile another thread peels off
+the association being used by the first thread.
+
+This patch replaces the BUG_ON call with a proper error handling. It
+will return -EPIPE to the original sendmsg call, similarly to what would
+have been done if the association wasn't found in the first place.
+
+Acked-by: Alexander Popov <alex.popov@linux.com>
+Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/socket.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -6962,7 +6962,8 @@ static int sctp_wait_for_sndbuf(struct s
+                */
+               release_sock(sk);
+               current_timeo = schedule_timeout(current_timeo);
+-              BUG_ON(sk != asoc->base.sk);
++              if (sk != asoc->base.sk)
++                      goto do_error;
+               lock_sock(sk);
+               *timeo_p = current_timeo;
diff --git a/queue-3.18/series b/queue-3.18/series
new file mode 100644 (file)
index 0000000..fc445eb
--- /dev/null
@@ -0,0 +1,15 @@
+can-fix-kernel-panic-at-security_sock_rcv_skb.patch
+ipv6-fix-ip6_tnl_parse_tlv_enc_lim.patch
+ipv6-pointer-math-error-in-ip6_tnl_parse_tlv_enc_lim.patch
+tcp-fix-0-divide-in-__tcp_select_window.patch
+net-use-a-work-queue-to-defer-net_disable_timestamp-work.patch
+ipv4-keep-skb-dst-around-in-presence-of-ip-options.patch
+netlabel-out-of-bound-access-in-cipso_v4_validate.patch
+mlx4-invoke-softirqs-after-napi_reschedule.patch
+sctp-avoid-bug_on-on-sctp_wait_for_sndbuf.patch
+sit-fix-a-double-free-on-error-path.patch
+ping-fix-a-null-pointer-dereference.patch
+l2tp-do-not-use-udp_ioctl.patch
+ip6_gre-fix-ip6gre_err-invalid-reads.patch
+ipv6-tcp-add-a-missing-tcp_v6_restore_cb.patch
+tcp-avoid-infinite-loop-in-tcp_splice_read.patch
diff --git a/queue-3.18/sit-fix-a-double-free-on-error-path.patch b/queue-3.18/sit-fix-a-double-free-on-error-path.patch
new file mode 100644 (file)
index 0000000..38943d4
--- /dev/null
@@ -0,0 +1,71 @@
+From foo@baz Mon Feb 20 15:15:52 CET 2017
+From: WANG Cong <xiyou.wangcong@gmail.com>
+Date: Wed, 8 Feb 2017 10:02:13 -0800
+Subject: sit: fix a double free on error path
+
+From: WANG Cong <xiyou.wangcong@gmail.com>
+
+
+[ Upstream commit d7426c69a1942b2b9b709bf66b944ff09f561484 ]
+
+Dmitry reported a double free in sit_init_net():
+
+  kernel BUG at mm/percpu.c:689!
+  invalid opcode: 0000 [#1] SMP KASAN
+  Dumping ftrace buffer:
+     (ftrace buffer empty)
+  Modules linked in:
+  CPU: 0 PID: 15692 Comm: syz-executor1 Not tainted 4.10.0-rc6-next-20170206 #1
+  Hardware name: Google Google Compute Engine/Google Compute Engine,
+  BIOS Google 01/01/2011
+  task: ffff8801c9cc27c0 task.stack: ffff88017d1d8000
+  RIP: 0010:pcpu_free_area+0x68b/0x810 mm/percpu.c:689
+  RSP: 0018:ffff88017d1df488 EFLAGS: 00010046
+  RAX: 0000000000010000 RBX: 00000000000007c0 RCX: ffffc90002829000
+  RDX: 0000000000010000 RSI: ffffffff81940efb RDI: ffff8801db841d94
+  RBP: ffff88017d1df590 R08: dffffc0000000000 R09: 1ffffffff0bb3bdd
+  R10: dffffc0000000000 R11: 00000000000135dd R12: ffff8801db841d80
+  R13: 0000000000038e40 R14: 00000000000007c0 R15: 00000000000007c0
+  FS:  00007f6ea608f700(0000) GS:ffff8801dbe00000(0000) knlGS:0000000000000000
+  CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+  CR2: 000000002000aff8 CR3: 00000001c8d44000 CR4: 00000000001426f0
+  DR0: 0000000020000000 DR1: 0000000020000000 DR2: 0000000000000000
+  DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000600
+  Call Trace:
+   free_percpu+0x212/0x520 mm/percpu.c:1264
+   ipip6_dev_free+0x43/0x60 net/ipv6/sit.c:1335
+   sit_init_net+0x3cb/0xa10 net/ipv6/sit.c:1831
+   ops_init+0x10a/0x530 net/core/net_namespace.c:115
+   setup_net+0x2ed/0x690 net/core/net_namespace.c:291
+   copy_net_ns+0x26c/0x530 net/core/net_namespace.c:396
+   create_new_namespaces+0x409/0x860 kernel/nsproxy.c:106
+   unshare_nsproxy_namespaces+0xae/0x1e0 kernel/nsproxy.c:205
+   SYSC_unshare kernel/fork.c:2281 [inline]
+   SyS_unshare+0x64e/0xfc0 kernel/fork.c:2231
+   entry_SYSCALL_64_fastpath+0x1f/0xc2
+
+This is because when tunnel->dst_cache init fails, we free dev->tstats
+once in ipip6_tunnel_init() and twice in sit_init_net(). This looks
+redundant but its ndo_uinit() does not seem enough to clean up everything
+here. So avoid this by setting dev->tstats to NULL after the first free,
+at least for -net.
+
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/sit.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/ipv6/sit.c
++++ b/net/ipv6/sit.c
+@@ -1388,6 +1388,7 @@ static int ipip6_tunnel_init(struct net_
+       tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst);
+       if (!tunnel->dst_cache) {
+               free_percpu(dev->tstats);
++              dev->tstats = NULL;
+               return -ENOMEM;
+       }
diff --git a/queue-3.18/tcp-avoid-infinite-loop-in-tcp_splice_read.patch b/queue-3.18/tcp-avoid-infinite-loop-in-tcp_splice_read.patch
new file mode 100644 (file)
index 0000000..96d5bf1
--- /dev/null
@@ -0,0 +1,47 @@
+From foo@baz Mon Feb 20 15:15:52 CET 2017
+From: Eric Dumazet <edumazet@google.com>
+Date: Fri, 3 Feb 2017 14:59:38 -0800
+Subject: tcp: avoid infinite loop in tcp_splice_read()
+
+From: Eric Dumazet <edumazet@google.com>
+
+
+[ Upstream commit ccf7abb93af09ad0868ae9033d1ca8108bdaec82 ]
+
+Splicing from TCP socket is vulnerable when a packet with URG flag is
+received and stored into receive queue.
+
+__tcp_splice_read() returns 0, and sk_wait_data() immediately
+returns since there is the problematic skb in queue.
+
+This is a nice way to burn cpu (aka infinite loop) and trigger
+soft lockups.
+
+Again, this gem was found by syzkaller tool.
+
+Fixes: 9c55e01c0cc8 ("[TCP]: Splice receive support.")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: Dmitry Vyukov  <dvyukov@google.com>
+Cc: Willy Tarreau <w@1wt.eu>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -775,6 +775,12 @@ ssize_t tcp_splice_read(struct socket *s
+                               ret = -EAGAIN;
+                               break;
+                       }
++                      /* if __tcp_splice_read() got nothing while we have
++                       * an skb in receive queue, we do not want to loop.
++                       * This might happen with URG data.
++                       */
++                      if (!skb_queue_empty(&sk->sk_receive_queue))
++                              break;
+                       sk_wait_data(sk, &timeo);
+                       if (signal_pending(current)) {
+                               ret = sock_intr_errno(timeo);
diff --git a/queue-3.18/tcp-fix-0-divide-in-__tcp_select_window.patch b/queue-3.18/tcp-fix-0-divide-in-__tcp_select_window.patch
new file mode 100644 (file)
index 0000000..09726be
--- /dev/null
@@ -0,0 +1,44 @@
+From foo@baz Mon Feb 20 15:15:52 CET 2017
+From: Eric Dumazet <edumazet@google.com>
+Date: Wed, 1 Feb 2017 08:33:53 -0800
+Subject: tcp: fix 0 divide in __tcp_select_window()
+
+From: Eric Dumazet <edumazet@google.com>
+
+
+[ Upstream commit 06425c308b92eaf60767bc71d359f4cbc7a561f8 ]
+
+syszkaller fuzzer was able to trigger a divide by zero, when
+TCP window scaling is not enabled.
+
+SO_RCVBUF can be used not only to increase sk_rcvbuf, also
+to decrease it below current receive buffers utilization.
+
+If mss is negative or 0, just return a zero TCP window.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: Dmitry Vyukov  <dvyukov@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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp_output.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -2291,9 +2291,11 @@ u32 __tcp_select_window(struct sock *sk)
+       int full_space = min_t(int, tp->window_clamp, allowed_space);
+       int window;
+-      if (mss > full_space)
++      if (unlikely(mss > full_space)) {
+               mss = full_space;
+-
++              if (mss <= 0)
++                      return 0;
++      }
+       if (free_space < (full_space >> 1)) {
+               icsk->icsk_ack.quick = 0;