From: Greg Kroah-Hartman Date: Mon, 20 Feb 2017 14:37:35 +0000 (+0100) Subject: 3.18 stuff X-Git-Tag: v4.4.51~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=33b4cb0e747d33aaee3e420083dbb8b9a83eddb2;p=thirdparty%2Fkernel%2Fstable-queue.git 3.18 stuff --- 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 index 00000000000..c035ec6ef5b --- /dev/null +++ b/queue-3.18/can-fix-kernel-panic-at-security_sock_rcv_skb.patch @@ -0,0 +1,205 @@ +From foo@baz Mon Feb 20 15:15:52 CET 2017 +From: Eric Dumazet +Date: Fri, 27 Jan 2017 08:11:44 -0800 +Subject: can: Fix kernel panic at security_sock_rcv_skb + +From: Eric Dumazet + + +[ 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: [] selinux_socket_sock_rcv_skb+0x65/0x2a0 + +Call Trace: + + [] security_sock_rcv_skb+0x4c/0x60 + [] sk_filter+0x41/0x210 + [] sock_queue_rcv_skb+0x53/0x3a0 + [] raw_rcv+0x2a3/0x3c0 + [] can_rcv_filter+0x12b/0x370 + [] can_receive+0xd9/0x120 + [] can_rcv+0xab/0x100 + [] __netif_receive_skb_core+0xd8c/0x11f0 + [] __netif_receive_skb+0x24/0xb0 + [] process_backlog+0x127/0x280 + [] net_rx_action+0x33b/0x4f0 + [] __do_softirq+0x184/0x440 + [] do_softirq_own_stack+0x1c/0x30 + + [] do_softirq.part.18+0x3b/0x40 + [] do_softirq+0x1d/0x20 + [] netif_rx_ni+0xe5/0x110 + [] slcan_receive_buf+0x507/0x520 + [] flush_to_ldisc+0x21c/0x230 + [] process_one_work+0x24f/0x670 + [] worker_thread+0x9d/0x6f0 + [] ? rescuer_thread+0x480/0x480 + [] kthread+0x12c/0x150 + [] ret_from_fork+0x3f/0x70 + +Reported-by: Zhang Yanmin +Signed-off-by: Eric Dumazet +Acked-by: Oliver Hartkopp +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..732e70e4df5 --- /dev/null +++ b/queue-3.18/ip6_gre-fix-ip6gre_err-invalid-reads.patch @@ -0,0 +1,101 @@ +From foo@baz Mon Feb 20 15:15:52 CET 2017 +From: Eric Dumazet +Date: Sat, 4 Feb 2017 23:18:55 -0800 +Subject: ip6_gre: fix ip6gre_err() invalid reads + +From: Eric Dumazet + + +[ 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 +Reported-by: Andrey Konovalov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include + + + 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 index 00000000000..e75f0b7a8f1 --- /dev/null +++ b/queue-3.18/ipv4-keep-skb-dst-around-in-presence-of-ip-options.patch @@ -0,0 +1,49 @@ +From foo@baz Mon Feb 20 15:15:52 CET 2017 +From: Eric Dumazet +Date: Sat, 4 Feb 2017 11:16:52 -0800 +Subject: ipv4: keep skb->dst around in presence of IP options + +From: Eric Dumazet + + +[ 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 +Reported-by: Andrey Konovalov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..2c1aa998e37 --- /dev/null +++ b/queue-3.18/ipv6-fix-ip6_tnl_parse_tlv_enc_lim.patch @@ -0,0 +1,103 @@ +From foo@baz Mon Feb 20 15:15:52 CET 2017 +From: Eric Dumazet +Date: Mon, 23 Jan 2017 16:43:06 -0800 +Subject: ipv6: fix ip6_tnl_parse_tlv_enc_lim() + +From: Eric Dumazet + + +[ 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 +Reported-by: Dmitry Vyukov +Cc: Willem de Bruijn +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..c1c3885b50f --- /dev/null +++ b/queue-3.18/ipv6-pointer-math-error-in-ip6_tnl_parse_tlv_enc_lim.patch @@ -0,0 +1,34 @@ +From foo@baz Mon Feb 20 15:15:52 CET 2017 +From: Dan Carpenter +Date: Wed, 1 Feb 2017 11:46:32 +0300 +Subject: ipv6: pointer math error in ip6_tnl_parse_tlv_enc_lim() + +From: Dan Carpenter + + +[ 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 +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..2325a54dea2 --- /dev/null +++ b/queue-3.18/ipv6-tcp-add-a-missing-tcp_v6_restore_cb.patch @@ -0,0 +1,73 @@ +From foo@baz Mon Feb 20 15:15:52 CET 2017 +From: Eric Dumazet +Date: Sun, 5 Feb 2017 20:23:22 -0800 +Subject: ipv6: tcp: add a missing tcp_v6_restore_cb() + +From: Eric Dumazet + + +[ 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 +Reported-by: Dmitry Vyukov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..b23060714ca --- /dev/null +++ b/queue-3.18/l2tp-do-not-use-udp_ioctl.patch @@ -0,0 +1,110 @@ +From foo@baz Mon Feb 20 15:15:52 CET 2017 +From: Eric Dumazet +Date: Thu, 9 Feb 2017 16:15:52 -0800 +Subject: l2tp: do not use udp_ioctl() + +From: Eric Dumazet + + +[ 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 +Reported-by: Andrey Konovalov +Acked-by: Paolo Abeni +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include + #include +@@ -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 index 00000000000..16d65b38ce6 --- /dev/null +++ b/queue-3.18/mlx4-invoke-softirqs-after-napi_reschedule.patch @@ -0,0 +1,45 @@ +From foo@baz Mon Feb 20 15:15:52 CET 2017 +From: Benjamin Poirier +Date: Mon, 6 Feb 2017 10:14:31 -0800 +Subject: mlx4: Invoke softirqs after napi_reschedule + +From: Benjamin Poirier + + +[ 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 +Signed-off-by: Benjamin Poirier +Acked-by: Eric Dumazet +Reviewed-by: Tariq Toukan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..a83f203e501 --- /dev/null +++ b/queue-3.18/net-use-a-work-queue-to-defer-net_disable_timestamp-work.patch @@ -0,0 +1,219 @@ +From foo@baz Mon Feb 20 15:15:52 CET 2017 +From: Eric Dumazet +Date: Thu, 2 Feb 2017 10:31:35 -0800 +Subject: net: use a work queue to defer net_disable_timestamp() work + +From: Eric Dumazet + + +[ 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: [] lock_sock +include/net/sock.h:1454 [inline] + #0: (sk_lock-AF_INET6){+.+.+.}, at: [] +rawv6_sendmsg+0x1e65/0x3ec0 net/ipv6/raw.c:919 + #1: (rcu_read_lock){......}, at: [] nf_hook +include/linux/netfilter.h:201 [inline] + #1: (rcu_read_lock){......}, at: [] +__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 +Reported-by: Dmitry Vyukov +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..329813f5aa5 --- /dev/null +++ b/queue-3.18/netlabel-out-of-bound-access-in-cipso_v4_validate.patch @@ -0,0 +1,53 @@ +From foo@baz Mon Feb 20 15:15:52 CET 2017 +From: Eric Dumazet +Date: Fri, 3 Feb 2017 00:03:26 -0800 +Subject: netlabel: out of bound access in cipso_v4_validate() + +From: Eric Dumazet + + +[ 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 +Reported-by: Dmitry Vyukov +Cc: Paul Moore +Acked-by: Paul Moore +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..c716ff7bab6 --- /dev/null +++ b/queue-3.18/ping-fix-a-null-pointer-dereference.patch @@ -0,0 +1,63 @@ +From foo@baz Mon Feb 20 15:15:52 CET 2017 +From: WANG Cong +Date: Tue, 7 Feb 2017 12:59:46 -0800 +Subject: ping: fix a null pointer dereference + +From: WANG Cong + + +[ 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 +Tested-by: Andrey Konovalov +Signed-off-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..cd7f09ae187 --- /dev/null +++ b/queue-3.18/sctp-avoid-bug_on-on-sctp_wait_for_sndbuf.patch @@ -0,0 +1,41 @@ +From foo@baz Mon Feb 20 15:15:52 CET 2017 +From: Marcelo Ricardo Leitner +Date: Mon, 6 Feb 2017 18:10:31 -0200 +Subject: sctp: avoid BUG_ON on sctp_wait_for_sndbuf + +From: Marcelo Ricardo Leitner + + +[ 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 +Signed-off-by: Marcelo Ricardo Leitner +Reviewed-by: Xin Long +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..fc445ebdcdb --- /dev/null +++ b/queue-3.18/series @@ -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 index 00000000000..38943d4c534 --- /dev/null +++ b/queue-3.18/sit-fix-a-double-free-on-error-path.patch @@ -0,0 +1,71 @@ +From foo@baz Mon Feb 20 15:15:52 CET 2017 +From: WANG Cong +Date: Wed, 8 Feb 2017 10:02:13 -0800 +Subject: sit: fix a double free on error path + +From: WANG Cong + + +[ 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 +Signed-off-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..96d5bf17c67 --- /dev/null +++ b/queue-3.18/tcp-avoid-infinite-loop-in-tcp_splice_read.patch @@ -0,0 +1,47 @@ +From foo@baz Mon Feb 20 15:15:52 CET 2017 +From: Eric Dumazet +Date: Fri, 3 Feb 2017 14:59:38 -0800 +Subject: tcp: avoid infinite loop in tcp_splice_read() + +From: Eric Dumazet + + +[ 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 +Reported-by: Dmitry Vyukov +Cc: Willy Tarreau +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..09726be286d --- /dev/null +++ b/queue-3.18/tcp-fix-0-divide-in-__tcp_select_window.patch @@ -0,0 +1,44 @@ +From foo@baz Mon Feb 20 15:15:52 CET 2017 +From: Eric Dumazet +Date: Wed, 1 Feb 2017 08:33:53 -0800 +Subject: tcp: fix 0 divide in __tcp_select_window() + +From: Eric Dumazet + + +[ 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 +Reported-by: Dmitry Vyukov +Acked-by: Neal Cardwell +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + 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; +