From: Greg Kroah-Hartman Date: Thu, 19 Oct 2017 12:51:51 +0000 (+0200) Subject: 4.4-stable patches X-Git-Tag: v3.18.77~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=87ab10dfc825623665518b097932d4ad0b779fc8;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: bpf-one-perf-event-close-won-t-free-bpf-program-attached-by-another-perf-event.patch bpf-verifier-reject-bpf_alu64-bpf_end.patch ip6_gre-skb_push-ipv6hdr-before-packing-the-header-in-ip6gre_header.patch isdn-i4l-fetch-the-ppp_write-buffer-in-one-shot.patch l2tp-avoid-schedule-while-atomic-in-exit_net.patch l2tp-fix-race-condition-in-l2tp_tunnel_delete.patch net-emac-fix-napi-poll-list-corruption.patch net-set-sk_prot_creator-when-cloning-sockets-to-the-right-proto.patch packet-hold-bind-lock-when-rebinding-to-fanout-hook.patch packet-in-packet_do_bind-test-fanout-with-bind_lock-held.patch packet-only-test-po-has_vnet_hdr-once-in-packet_snd.patch sctp-potential-read-out-of-bounds-in-sctp_ulpevent_type_enabled.patch tipc-use-only-positive-error-codes-in-messages.patch tun-bail-out-from-tun_get_user-if-the-skb-is-empty.patch udpv6-fix-the-checksum-computation-when-hw-checksum-does-not-apply.patch vti-fix-use-after-free-in-vti_tunnel_xmit-vti6_tnl_xmit.patch --- diff --git a/queue-4.4/bpf-one-perf-event-close-won-t-free-bpf-program-attached-by-another-perf-event.patch b/queue-4.4/bpf-one-perf-event-close-won-t-free-bpf-program-attached-by-another-perf-event.patch new file mode 100644 index 00000000000..363dce67398 --- /dev/null +++ b/queue-4.4/bpf-one-perf-event-close-won-t-free-bpf-program-attached-by-another-perf-event.patch @@ -0,0 +1,64 @@ +From foo@baz Thu Oct 19 14:05:19 CEST 2017 +From: Yonghong Song +Date: Mon, 18 Sep 2017 16:38:36 -0700 +Subject: bpf: one perf event close won't free bpf program attached by another perf event + +From: Yonghong Song + + +[ Upstream commit ec9dd352d591f0c90402ec67a317c1ed4fb2e638 ] + +This patch fixes a bug exhibited by the following scenario: + 1. fd1 = perf_event_open with attr.config = ID1 + 2. attach bpf program prog1 to fd1 + 3. fd2 = perf_event_open with attr.config = ID1 + + 4. user program closes fd2 and prog1 is detached from the tracepoint. + 5. user program with fd1 does not work properly as tracepoint + no output any more. + +The issue happens at step 4. Multiple perf_event_open can be called +successfully, but only one bpf prog pointer in the tp_event. In the +current logic, any fd release for the same tp_event will free +the tp_event->prog. + +The fix is to free tp_event->prog only when the closing fd +corresponds to the one which registered the program. + +Signed-off-by: Yonghong Song +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/trace_events.h | 1 + + kernel/events/core.c | 3 ++- + 2 files changed, 3 insertions(+), 1 deletion(-) + +--- a/include/linux/trace_events.h ++++ b/include/linux/trace_events.h +@@ -301,6 +301,7 @@ struct trace_event_call { + int perf_refcount; + struct hlist_head __percpu *perf_events; + struct bpf_prog *prog; ++ struct perf_event *bpf_prog_owner; + + int (*perf_perm)(struct trace_event_call *, + struct perf_event *); +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -7108,6 +7108,7 @@ static int perf_event_set_bpf_prog(struc + } + + event->tp_event->prog = prog; ++ event->tp_event->bpf_prog_owner = event; + + return 0; + } +@@ -7120,7 +7121,7 @@ static void perf_event_free_bpf_prog(str + return; + + prog = event->tp_event->prog; +- if (prog) { ++ if (prog && event->tp_event->bpf_prog_owner == event) { + event->tp_event->prog = NULL; + bpf_prog_put_rcu(prog); + } diff --git a/queue-4.4/bpf-verifier-reject-bpf_alu64-bpf_end.patch b/queue-4.4/bpf-verifier-reject-bpf_alu64-bpf_end.patch new file mode 100644 index 00000000000..a06682875eb --- /dev/null +++ b/queue-4.4/bpf-verifier-reject-bpf_alu64-bpf_end.patch @@ -0,0 +1,35 @@ +From foo@baz Thu Oct 19 13:36:51 CEST 2017 +From: Edward Cree +Date: Fri, 15 Sep 2017 14:37:38 +0100 +Subject: bpf/verifier: reject BPF_ALU64|BPF_END + +From: Edward Cree + + +[ Upstream commit e67b8a685c7c984e834e3181ef4619cd7025a136 ] + +Neither ___bpf_prog_run nor the JITs accept it. +Also adds a new test case. + +Fixes: 17a5267067f3 ("bpf: verifier (add verifier core)") +Signed-off-by: Edward Cree +Acked-by: Alexei Starovoitov +Acked-by: Daniel Borkmann +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + kernel/bpf/verifier.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -1033,7 +1033,8 @@ static int check_alu_op(struct verifier_ + } + } else { + if (insn->src_reg != BPF_REG_0 || insn->off != 0 || +- (insn->imm != 16 && insn->imm != 32 && insn->imm != 64)) { ++ (insn->imm != 16 && insn->imm != 32 && insn->imm != 64) || ++ BPF_CLASS(insn->code) == BPF_ALU64) { + verbose("BPF_END uses reserved fields\n"); + return -EINVAL; + } diff --git a/queue-4.4/ip6_gre-skb_push-ipv6hdr-before-packing-the-header-in-ip6gre_header.patch b/queue-4.4/ip6_gre-skb_push-ipv6hdr-before-packing-the-header-in-ip6gre_header.patch new file mode 100644 index 00000000000..3eb2648ab99 --- /dev/null +++ b/queue-4.4/ip6_gre-skb_push-ipv6hdr-before-packing-the-header-in-ip6gre_header.patch @@ -0,0 +1,76 @@ +From foo@baz Thu Oct 19 14:05:19 CEST 2017 +From: Xin Long +Date: Fri, 15 Sep 2017 12:00:07 +0800 +Subject: ip6_gre: skb_push ipv6hdr before packing the header in ip6gre_header + +From: Xin Long + + +[ Upstream commit 76cc0d3282d4b933fa144fa41fbc5318e0fdca24 ] + +Now in ip6gre_header before packing the ipv6 header, it skb_push t->hlen +which only includes encap_hlen + tun_hlen. It means greh and inner header +would be over written by ipv6 stuff and ipv6h might have no chance to set +up. + +Jianlin found this issue when using remote any on ip6_gre, the packets he +captured on gre dev are truncated: + +22:50:26.210866 Out ethertype IPv6 (0x86dd), length 120: truncated-ip6 -\ +8128 bytes missing!(flowlabel 0x92f40, hlim 0, next-header Options (0) \ +payload length: 8192) ::1:2000:0 > ::1:0:86dd: HBH [trunc] ip-proto-128 \ +8184 + +It should also skb_push ipv6hdr so that ipv6h points to the right position +to set ipv6 stuff up. + +This patch is to skb_push hlen + sizeof(*ipv6h) and also fix some indents +in ip6gre_header. + +Fixes: c12b395a4664 ("gre: Support GRE over IPv6") +Reported-by: Jianlin Shi +Signed-off-by: Xin Long +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/ip6_gre.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -1173,24 +1173,25 @@ static int ip6gre_tunnel_change_mtu(stru + } + + static int ip6gre_header(struct sk_buff *skb, struct net_device *dev, +- unsigned short type, +- const void *daddr, const void *saddr, unsigned int len) ++ unsigned short type, const void *daddr, ++ const void *saddr, unsigned int len) + { + struct ip6_tnl *t = netdev_priv(dev); +- struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb_push(skb, t->hlen); +- __be16 *p = (__be16 *)(ipv6h+1); ++ struct ipv6hdr *ipv6h; ++ __be16 *p; + +- ip6_flow_hdr(ipv6h, 0, +- ip6_make_flowlabel(dev_net(dev), skb, +- t->fl.u.ip6.flowlabel, true, +- &t->fl.u.ip6)); ++ ipv6h = (struct ipv6hdr *)skb_push(skb, t->hlen + sizeof(*ipv6h)); ++ ip6_flow_hdr(ipv6h, 0, ip6_make_flowlabel(dev_net(dev), skb, ++ t->fl.u.ip6.flowlabel, ++ true, &t->fl.u.ip6)); + ipv6h->hop_limit = t->parms.hop_limit; + ipv6h->nexthdr = NEXTHDR_GRE; + ipv6h->saddr = t->parms.laddr; + ipv6h->daddr = t->parms.raddr; + +- p[0] = t->parms.o_flags; +- p[1] = htons(type); ++ p = (__be16 *)(ipv6h + 1); ++ p[0] = t->parms.o_flags; ++ p[1] = htons(type); + + /* + * Set the source hardware address. diff --git a/queue-4.4/isdn-i4l-fetch-the-ppp_write-buffer-in-one-shot.patch b/queue-4.4/isdn-i4l-fetch-the-ppp_write-buffer-in-one-shot.patch new file mode 100644 index 00000000000..9fbccdc6071 --- /dev/null +++ b/queue-4.4/isdn-i4l-fetch-the-ppp_write-buffer-in-one-shot.patch @@ -0,0 +1,104 @@ +From foo@baz Thu Oct 19 14:05:19 CEST 2017 +From: Meng Xu +Date: Tue, 19 Sep 2017 21:49:55 -0400 +Subject: isdn/i4l: fetch the ppp_write buffer in one shot + +From: Meng Xu + + +[ Upstream commit 02388bf87f72e1d47174cd8f81c34443920eb5a0 ] + +In isdn_ppp_write(), the header (i.e., protobuf) of the buffer is +fetched twice from userspace. The first fetch is used to peek at the +protocol of the message and reset the huptimer if necessary; while the +second fetch copies in the whole buffer. However, given that buf resides +in userspace memory, a user process can race to change its memory content +across fetches. By doing so, we can either avoid resetting the huptimer +for any type of packets (by first setting proto to PPP_LCP and later +change to the actual type) or force resetting the huptimer for LCP +packets. + +This patch changes this double-fetch behavior into two single fetches +decided by condition (lp->isdn_device < 0 || lp->isdn_channel <0). +A more detailed discussion can be found at +https://marc.info/?l=linux-kernel&m=150586376926123&w=2 + +Signed-off-by: Meng Xu +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/isdn/i4l/isdn_ppp.c | 37 +++++++++++++++++++++++++------------ + 1 file changed, 25 insertions(+), 12 deletions(-) + +--- a/drivers/isdn/i4l/isdn_ppp.c ++++ b/drivers/isdn/i4l/isdn_ppp.c +@@ -828,7 +828,6 @@ isdn_ppp_write(int min, struct file *fil + isdn_net_local *lp; + struct ippp_struct *is; + int proto; +- unsigned char protobuf[4]; + + is = file->private_data; + +@@ -842,24 +841,28 @@ isdn_ppp_write(int min, struct file *fil + if (!lp) + printk(KERN_DEBUG "isdn_ppp_write: lp == NULL\n"); + else { +- /* +- * Don't reset huptimer for +- * LCP packets. (Echo requests). +- */ +- if (copy_from_user(protobuf, buf, 4)) +- return -EFAULT; +- proto = PPP_PROTOCOL(protobuf); +- if (proto != PPP_LCP) +- lp->huptimer = 0; ++ if (lp->isdn_device < 0 || lp->isdn_channel < 0) { ++ unsigned char protobuf[4]; ++ /* ++ * Don't reset huptimer for ++ * LCP packets. (Echo requests). ++ */ ++ if (copy_from_user(protobuf, buf, 4)) ++ return -EFAULT; ++ ++ proto = PPP_PROTOCOL(protobuf); ++ if (proto != PPP_LCP) ++ lp->huptimer = 0; + +- if (lp->isdn_device < 0 || lp->isdn_channel < 0) + return 0; ++ } + + if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) && + lp->dialstate == 0 && + (lp->flags & ISDN_NET_CONNECTED)) { + unsigned short hl; + struct sk_buff *skb; ++ unsigned char *cpy_buf; + /* + * we need to reserve enough space in front of + * sk_buff. old call to dev_alloc_skb only reserved +@@ -872,11 +875,21 @@ isdn_ppp_write(int min, struct file *fil + return count; + } + skb_reserve(skb, hl); +- if (copy_from_user(skb_put(skb, count), buf, count)) ++ cpy_buf = skb_put(skb, count); ++ if (copy_from_user(cpy_buf, buf, count)) + { + kfree_skb(skb); + return -EFAULT; + } ++ ++ /* ++ * Don't reset huptimer for ++ * LCP packets. (Echo requests). ++ */ ++ proto = PPP_PROTOCOL(cpy_buf); ++ if (proto != PPP_LCP) ++ lp->huptimer = 0; ++ + if (is->debug & 0x40) { + printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len); + isdn_ppp_frame_log("xmit", skb->data, skb->len, 32, is->unit, lp->ppp_slot); diff --git a/queue-4.4/l2tp-avoid-schedule-while-atomic-in-exit_net.patch b/queue-4.4/l2tp-avoid-schedule-while-atomic-in-exit_net.patch new file mode 100644 index 00000000000..c5f6e24b294 --- /dev/null +++ b/queue-4.4/l2tp-avoid-schedule-while-atomic-in-exit_net.patch @@ -0,0 +1,100 @@ +From foo@baz Thu Oct 19 14:05:19 CEST 2017 +From: Ridge Kennedy +Date: Wed, 22 Feb 2017 14:59:49 +1300 +Subject: l2tp: Avoid schedule while atomic in exit_net + +From: Ridge Kennedy + + +[ Upstream commit 12d656af4e3d2781b9b9f52538593e1717e7c979 ] + +While destroying a network namespace that contains a L2TP tunnel a +"BUG: scheduling while atomic" can be observed. + +Enabling lockdep shows that this is happening because l2tp_exit_net() +is calling l2tp_tunnel_closeall() (via l2tp_tunnel_delete()) from +within an RCU critical section. + +l2tp_exit_net() takes rcu_read_lock_bh() + << list_for_each_entry_rcu() >> + l2tp_tunnel_delete() + l2tp_tunnel_closeall() + __l2tp_session_unhash() + synchronize_rcu() << Illegal inside RCU critical section >> + +BUG: sleeping function called from invalid context +in_atomic(): 1, irqs_disabled(): 0, pid: 86, name: kworker/u16:2 +INFO: lockdep is turned off. +CPU: 2 PID: 86 Comm: kworker/u16:2 Tainted: G W O 4.4.6-at1 #2 +Hardware name: Xen HVM domU, BIOS 4.6.1-xs125300 05/09/2016 +Workqueue: netns cleanup_net + 0000000000000000 ffff880202417b90 ffffffff812b0013 ffff880202410ac0 + ffffffff81870de8 ffff880202417bb8 ffffffff8107aee8 ffffffff81870de8 + 0000000000000c51 0000000000000000 ffff880202417be0 ffffffff8107b024 +Call Trace: + [] dump_stack+0x85/0xc2 + [] ___might_sleep+0x148/0x240 + [] __might_sleep+0x44/0x80 + [] synchronize_sched+0x2d/0xe0 + [] ? trace_hardirqs_on+0xd/0x10 + [] ? __local_bh_enable_ip+0x6b/0xc0 + [] ? _raw_spin_unlock_bh+0x30/0x40 + [] __l2tp_session_unhash+0x172/0x220 + [] ? __l2tp_session_unhash+0x87/0x220 + [] l2tp_tunnel_closeall+0x9b/0x140 + [] l2tp_tunnel_delete+0x14/0x60 + [] l2tp_exit_net+0x110/0x270 + [] ? l2tp_exit_net+0x9c/0x270 + [] ops_exit_list.isra.6+0x33/0x60 + [] cleanup_net+0x1b6/0x280 + ... + +This bug can easily be reproduced with a few steps: + + $ sudo unshare -n bash # Create a shell in a new namespace + # ip link set lo up + # ip addr add 127.0.0.1 dev lo + # ip l2tp add tunnel remote 127.0.0.1 local 127.0.0.1 tunnel_id 1 \ + peer_tunnel_id 1 udp_sport 50000 udp_dport 50000 + # ip l2tp add session name foo tunnel_id 1 session_id 1 \ + peer_session_id 1 + # ip link set foo up + # exit # Exit the shell, in turn exiting the namespace + $ dmesg + ... + [942121.089216] BUG: scheduling while atomic: kworker/u16:3/13872/0x00000200 + ... + +To fix this, move the call to l2tp_tunnel_closeall() out of the RCU +critical section, and instead call it from l2tp_tunnel_del_work(), which +is running from the l2tp_wq workqueue. + +Fixes: 2b551c6e7d5b ("l2tp: close sessions before initiating tunnel delete") +Signed-off-by: Ridge Kennedy +Acked-by: Guillaume Nault +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/l2tp/l2tp_core.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -1321,6 +1321,9 @@ static void l2tp_tunnel_del_work(struct + struct sock *sk = NULL; + + tunnel = container_of(work, struct l2tp_tunnel, del_work); ++ ++ l2tp_tunnel_closeall(tunnel); ++ + sk = l2tp_tunnel_sock_lookup(tunnel); + if (!sk) + goto out; +@@ -1643,7 +1646,6 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create); + int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) + { + l2tp_tunnel_inc_refcount(tunnel); +- l2tp_tunnel_closeall(tunnel); + if (false == queue_work(l2tp_wq, &tunnel->del_work)) { + l2tp_tunnel_dec_refcount(tunnel); + return 1; diff --git a/queue-4.4/l2tp-fix-race-condition-in-l2tp_tunnel_delete.patch b/queue-4.4/l2tp-fix-race-condition-in-l2tp_tunnel_delete.patch new file mode 100644 index 00000000000..1068a2132dd --- /dev/null +++ b/queue-4.4/l2tp-fix-race-condition-in-l2tp_tunnel_delete.patch @@ -0,0 +1,85 @@ +From foo@baz Thu Oct 19 14:05:19 CEST 2017 +From: Sabrina Dubroca +Date: Tue, 26 Sep 2017 16:16:43 +0200 +Subject: l2tp: fix race condition in l2tp_tunnel_delete + +From: Sabrina Dubroca + + +[ Upstream commit 62b982eeb4589b2e6d7c01a90590e3a4c2b2ca19 ] + +If we try to delete the same tunnel twice, the first delete operation +does a lookup (l2tp_tunnel_get), finds the tunnel, calls +l2tp_tunnel_delete, which queues it for deletion by +l2tp_tunnel_del_work. + +The second delete operation also finds the tunnel and calls +l2tp_tunnel_delete. If the workqueue has already fired and started +running l2tp_tunnel_del_work, then l2tp_tunnel_delete will queue the +same tunnel a second time, and try to free the socket again. + +Add a dead flag to prevent firing the workqueue twice. Then we can +remove the check of queue_work's result that was meant to prevent that +race but doesn't. + +Reproducer: + + ip l2tp add tunnel tunnel_id 3000 peer_tunnel_id 4000 local 192.168.0.2 remote 192.168.0.1 encap udp udp_sport 5000 udp_dport 6000 + ip l2tp add session name l2tp1 tunnel_id 3000 session_id 1000 peer_session_id 2000 + ip link set l2tp1 up + ip l2tp del tunnel tunnel_id 3000 + ip l2tp del tunnel tunnel_id 3000 + +Fixes: f8ccac0e4493 ("l2tp: put tunnel socket release on a workqueue") +Reported-by: Jianlin Shi +Signed-off-by: Sabrina Dubroca +Acked-by: Guillaume Nault +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/l2tp/l2tp_core.c | 10 ++++------ + net/l2tp/l2tp_core.h | 5 ++++- + 2 files changed, 8 insertions(+), 7 deletions(-) + +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -1643,14 +1643,12 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create); + + /* This function is used by the netlink TUNNEL_DELETE command. + */ +-int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) ++void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) + { +- l2tp_tunnel_inc_refcount(tunnel); +- if (false == queue_work(l2tp_wq, &tunnel->del_work)) { +- l2tp_tunnel_dec_refcount(tunnel); +- return 1; ++ if (!test_and_set_bit(0, &tunnel->dead)) { ++ l2tp_tunnel_inc_refcount(tunnel); ++ queue_work(l2tp_wq, &tunnel->del_work); + } +- return 0; + } + EXPORT_SYMBOL_GPL(l2tp_tunnel_delete); + +--- a/net/l2tp/l2tp_core.h ++++ b/net/l2tp/l2tp_core.h +@@ -169,6 +169,9 @@ struct l2tp_tunnel_cfg { + + struct l2tp_tunnel { + int magic; /* Should be L2TP_TUNNEL_MAGIC */ ++ ++ unsigned long dead; ++ + struct rcu_head rcu; + rwlock_t hlist_lock; /* protect session_hlist */ + struct hlist_head session_hlist[L2TP_HASH_SIZE]; +@@ -253,7 +256,7 @@ int l2tp_tunnel_create(struct net *net, + u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, + struct l2tp_tunnel **tunnelp); + void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel); +-int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel); ++void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel); + struct l2tp_session *l2tp_session_create(int priv_size, + struct l2tp_tunnel *tunnel, + u32 session_id, u32 peer_session_id, diff --git a/queue-4.4/net-emac-fix-napi-poll-list-corruption.patch b/queue-4.4/net-emac-fix-napi-poll-list-corruption.patch new file mode 100644 index 00000000000..7ec3cc718b6 --- /dev/null +++ b/queue-4.4/net-emac-fix-napi-poll-list-corruption.patch @@ -0,0 +1,54 @@ +From foo@baz Thu Oct 19 14:05:19 CEST 2017 +From: Christian Lamparter +Date: Tue, 19 Sep 2017 19:35:18 +0200 +Subject: net: emac: Fix napi poll list corruption + +From: Christian Lamparter + + +[ Upstream commit f55956065ec94e3e9371463d693a1029c4cc3007 ] + +This patch is pretty much a carbon copy of +commit 3079c652141f ("caif: Fix napi poll list corruption") +with "caif" replaced by "emac". + +The commit d75b1ade567f ("net: less interrupt masking in NAPI") +breaks emac. + +It is now required that if the entire budget is consumed when poll +returns, the napi poll_list must remain empty. However, like some +other drivers emac tries to do a last-ditch check and if there is +more work it will call napi_reschedule and then immediately process +some of this new work. Should the entire budget be consumed while +processing such new work then we will violate the new caller +contract. + +This patch fixes this by not touching any work when we reschedule +in emac. + +Signed-off-by: Christian Lamparter +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/ibm/emac/mal.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/ethernet/ibm/emac/mal.c ++++ b/drivers/net/ethernet/ibm/emac/mal.c +@@ -402,7 +402,7 @@ static int mal_poll(struct napi_struct * + unsigned long flags; + + MAL_DBG2(mal, "poll(%d)" NL, budget); +- again: ++ + /* Process TX skbs */ + list_for_each(l, &mal->poll_list) { + struct mal_commac *mc = +@@ -451,7 +451,6 @@ static int mal_poll(struct napi_struct * + spin_lock_irqsave(&mal->lock, flags); + mal_disable_eob_irq(mal); + spin_unlock_irqrestore(&mal->lock, flags); +- goto again; + } + mc->ops->poll_tx(mc->dev); + } diff --git a/queue-4.4/net-set-sk_prot_creator-when-cloning-sockets-to-the-right-proto.patch b/queue-4.4/net-set-sk_prot_creator-when-cloning-sockets-to-the-right-proto.patch new file mode 100644 index 00000000000..f3133bf062a --- /dev/null +++ b/queue-4.4/net-set-sk_prot_creator-when-cloning-sockets-to-the-right-proto.patch @@ -0,0 +1,107 @@ +From foo@baz Thu Oct 19 14:05:19 CEST 2017 +From: Christoph Paasch +Date: Tue, 26 Sep 2017 17:38:50 -0700 +Subject: net: Set sk_prot_creator when cloning sockets to the right proto + +From: Christoph Paasch + + +[ Upstream commit 9d538fa60bad4f7b23193c89e843797a1cf71ef3 ] + +sk->sk_prot and sk->sk_prot_creator can differ when the app uses +IPV6_ADDRFORM (transforming an IPv6-socket to an IPv4-one). +Which is why sk_prot_creator is there to make sure that sk_prot_free() +does the kmem_cache_free() on the right kmem_cache slab. + +Now, if such a socket gets transformed back to a listening socket (using +connect() with AF_UNSPEC) we will allocate an IPv4 tcp_sock through +sk_clone_lock() when a new connection comes in. But sk_prot_creator will +still point to the IPv6 kmem_cache (as everything got copied in +sk_clone_lock()). When freeing, we will thus put this +memory back into the IPv6 kmem_cache although it was allocated in the +IPv4 cache. I have seen memory corruption happening because of this. + +With slub-debugging and MEMCG_KMEM enabled this gives the warning + "cache_from_obj: Wrong slab cache. TCPv6 but object is from TCP" + +A C-program to trigger this: + +void main(void) +{ + int fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); + int new_fd, newest_fd, client_fd; + struct sockaddr_in6 bind_addr; + struct sockaddr_in bind_addr4, client_addr1, client_addr2; + struct sockaddr unsp; + int val; + + memset(&bind_addr, 0, sizeof(bind_addr)); + bind_addr.sin6_family = AF_INET6; + bind_addr.sin6_port = ntohs(42424); + + memset(&client_addr1, 0, sizeof(client_addr1)); + client_addr1.sin_family = AF_INET; + client_addr1.sin_port = ntohs(42424); + client_addr1.sin_addr.s_addr = inet_addr("127.0.0.1"); + + memset(&client_addr2, 0, sizeof(client_addr2)); + client_addr2.sin_family = AF_INET; + client_addr2.sin_port = ntohs(42421); + client_addr2.sin_addr.s_addr = inet_addr("127.0.0.1"); + + memset(&unsp, 0, sizeof(unsp)); + unsp.sa_family = AF_UNSPEC; + + bind(fd, (struct sockaddr *)&bind_addr, sizeof(bind_addr)); + + listen(fd, 5); + + client_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + connect(client_fd, (struct sockaddr *)&client_addr1, sizeof(client_addr1)); + new_fd = accept(fd, NULL, NULL); + close(fd); + + val = AF_INET; + setsockopt(new_fd, SOL_IPV6, IPV6_ADDRFORM, &val, sizeof(val)); + + connect(new_fd, &unsp, sizeof(unsp)); + + memset(&bind_addr4, 0, sizeof(bind_addr4)); + bind_addr4.sin_family = AF_INET; + bind_addr4.sin_port = ntohs(42421); + bind(new_fd, (struct sockaddr *)&bind_addr4, sizeof(bind_addr4)); + + listen(new_fd, 5); + + client_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + connect(client_fd, (struct sockaddr *)&client_addr2, sizeof(client_addr2)); + + newest_fd = accept(new_fd, NULL, NULL); + close(new_fd); + + close(client_fd); + close(new_fd); +} + +As far as I can see, this bug has been there since the beginning of the +git-days. + +Signed-off-by: Christoph Paasch +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/sock.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -1516,6 +1516,8 @@ struct sock *sk_clone_lock(const struct + + sock_copy(newsk, sk); + ++ newsk->sk_prot_creator = sk->sk_prot; ++ + /* SANITY */ + if (likely(newsk->sk_net_refcnt)) + get_net(sock_net(newsk)); diff --git a/queue-4.4/packet-hold-bind-lock-when-rebinding-to-fanout-hook.patch b/queue-4.4/packet-hold-bind-lock-when-rebinding-to-fanout-hook.patch new file mode 100644 index 00000000000..3e6e7a0c9fb --- /dev/null +++ b/queue-4.4/packet-hold-bind-lock-when-rebinding-to-fanout-hook.patch @@ -0,0 +1,74 @@ +From foo@baz Thu Oct 19 14:05:19 CEST 2017 +From: Willem de Bruijn +Date: Thu, 14 Sep 2017 17:14:41 -0400 +Subject: packet: hold bind lock when rebinding to fanout hook + +From: Willem de Bruijn + + +[ Upstream commit 008ba2a13f2d04c947adc536d19debb8fe66f110 ] + +Packet socket bind operations must hold the po->bind_lock. This keeps +po->running consistent with whether the socket is actually on a ptype +list to receive packets. + +fanout_add unbinds a socket and its packet_rcv/tpacket_rcv call, then +binds the fanout object to receive through packet_rcv_fanout. + +Make it hold the po->bind_lock when testing po->running and rebinding. +Else, it can race with other rebind operations, such as that in +packet_set_ring from packet_rcv to tpacket_rcv. Concurrent updates +can result in a socket being added to a fanout group twice, causing +use-after-free KASAN bug reports, among others. + +Reported independently by both trinity and syzkaller. +Verified that the syzkaller reproducer passes after this patch. + +Fixes: dc99f600698d ("packet: Add fanout support.") +Reported-by: nixioaming +Signed-off-by: Willem de Bruijn +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/packet/af_packet.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -1652,10 +1652,6 @@ static int fanout_add(struct sock *sk, u + + mutex_lock(&fanout_mutex); + +- err = -EINVAL; +- if (!po->running) +- goto out; +- + err = -EALREADY; + if (po->fanout) + goto out; +@@ -1704,7 +1700,10 @@ static int fanout_add(struct sock *sk, u + list_add(&match->list, &fanout_list); + } + err = -EINVAL; +- if (match->type == type && ++ ++ spin_lock(&po->bind_lock); ++ if (po->running && ++ match->type == type && + match->prot_hook.type == po->prot_hook.type && + match->prot_hook.dev == po->prot_hook.dev) { + err = -ENOSPC; +@@ -1716,6 +1715,13 @@ static int fanout_add(struct sock *sk, u + err = 0; + } + } ++ spin_unlock(&po->bind_lock); ++ ++ if (err && !refcount_read(&match->sk_ref)) { ++ list_del(&match->list); ++ kfree(match); ++ } ++ + out: + if (err && rollover) { + kfree(rollover); diff --git a/queue-4.4/packet-in-packet_do_bind-test-fanout-with-bind_lock-held.patch b/queue-4.4/packet-in-packet_do_bind-test-fanout-with-bind_lock-held.patch new file mode 100644 index 00000000000..e378ccf884d --- /dev/null +++ b/queue-4.4/packet-in-packet_do_bind-test-fanout-with-bind_lock-held.patch @@ -0,0 +1,53 @@ +From foo@baz Thu Oct 19 14:05:19 CEST 2017 +From: Willem de Bruijn +Date: Tue, 26 Sep 2017 12:19:37 -0400 +Subject: packet: in packet_do_bind, test fanout with bind_lock held + +From: Willem de Bruijn + + +[ Upstream commit 4971613c1639d8e5f102c4e797c3bf8f83a5a69e ] + +Once a socket has po->fanout set, it remains a member of the group +until it is destroyed. The prot_hook must be constant and identical +across sockets in the group. + +If fanout_add races with packet_do_bind between the test of po->fanout +and taking the lock, the bind call may make type or dev inconsistent +with that of the fanout group. + +Hold po->bind_lock when testing po->fanout to avoid this race. + +I had to introduce artificial delay (local_bh_enable) to actually +observe the race. + +Fixes: dc99f600698d ("packet: Add fanout support.") +Signed-off-by: Willem de Bruijn +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/packet/af_packet.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -2944,13 +2944,15 @@ static int packet_do_bind(struct sock *s + int ret = 0; + bool unlisted = false; + +- if (po->fanout) +- return -EINVAL; +- + lock_sock(sk); + spin_lock(&po->bind_lock); + rcu_read_lock(); + ++ if (po->fanout) { ++ ret = -EINVAL; ++ goto out_unlock; ++ } ++ + if (name) { + dev = dev_get_by_name_rcu(sock_net(sk), name); + if (!dev) { diff --git a/queue-4.4/packet-only-test-po-has_vnet_hdr-once-in-packet_snd.patch b/queue-4.4/packet-only-test-po-has_vnet_hdr-once-in-packet_snd.patch new file mode 100644 index 00000000000..462b8e37d6a --- /dev/null +++ b/queue-4.4/packet-only-test-po-has_vnet_hdr-once-in-packet_snd.patch @@ -0,0 +1,62 @@ +From foo@baz Thu Oct 19 14:05:19 CEST 2017 +From: Willem de Bruijn +Date: Tue, 26 Sep 2017 12:20:17 -0400 +Subject: packet: only test po->has_vnet_hdr once in packet_snd + +From: Willem de Bruijn + + +[ Upstream commit da7c9561015e93d10fe6aab73e9288e0d09d65a6 ] + +Packet socket option po->has_vnet_hdr can be updated concurrently with +other operations if no ring is attached. + +Do not test the option twice in packet_snd, as the value may change in +between calls. A race on setsockopt disable may cause a packet > mtu +to be sent without having GSO options set. + +Fixes: bfd5f4a3d605 ("packet: Add GSO/csum offload support.") +Signed-off-by: Willem de Bruijn +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/packet/af_packet.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -1717,7 +1717,7 @@ static int fanout_add(struct sock *sk, u + } + spin_unlock(&po->bind_lock); + +- if (err && !refcount_read(&match->sk_ref)) { ++ if (err && !atomic_read(&match->sk_ref)) { + list_del(&match->list); + kfree(match); + } +@@ -2656,6 +2656,7 @@ static int packet_snd(struct socket *soc + int vnet_hdr_len; + struct packet_sock *po = pkt_sk(sk); + unsigned short gso_type = 0; ++ bool has_vnet_hdr = false; + int hlen, tlen, linear; + int extra_len = 0; + ssize_t n; +@@ -2743,6 +2744,7 @@ static int packet_snd(struct socket *soc + goto out_unlock; + + } ++ has_vnet_hdr = true; + } + + if (unlikely(sock_flag(sk, SOCK_NOFCS))) { +@@ -2802,7 +2804,7 @@ static int packet_snd(struct socket *soc + + packet_pick_tx_queue(dev, skb); + +- if (po->has_vnet_hdr) { ++ if (has_vnet_hdr) { + if (vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { + u16 s = __virtio16_to_cpu(vio_le(), vnet_hdr.csum_start); + u16 o = __virtio16_to_cpu(vio_le(), vnet_hdr.csum_offset); diff --git a/queue-4.4/sctp-potential-read-out-of-bounds-in-sctp_ulpevent_type_enabled.patch b/queue-4.4/sctp-potential-read-out-of-bounds-in-sctp_ulpevent_type_enabled.patch new file mode 100644 index 00000000000..ad95a50b4cd --- /dev/null +++ b/queue-4.4/sctp-potential-read-out-of-bounds-in-sctp_ulpevent_type_enabled.patch @@ -0,0 +1,46 @@ +From foo@baz Thu Oct 19 13:36:51 CEST 2017 +From: Dan Carpenter +Date: Thu, 14 Sep 2017 02:00:54 +0300 +Subject: sctp: potential read out of bounds in sctp_ulpevent_type_enabled() + +From: Dan Carpenter + + +[ Upstream commit fa5f7b51fc3080c2b195fa87c7eca7c05e56f673 ] + +This code causes a static checker warning because Smatch doesn't trust +anything that comes from skb->data. I've reviewed this code and I do +think skb->data can be controlled by the user here. + +The sctp_event_subscribe struct has 13 __u8 fields and we want to see +if ours is non-zero. sn_type can be any value in the 0-USHRT_MAX range. +We're subtracting SCTP_SN_TYPE_BASE which is 1 << 15 so we could read +either before the start of the struct or after the end. + +This is a very old bug and it's surprising that it would go undetected +for so long but my theory is that it just doesn't have a big impact so +it would be hard to notice. + +Signed-off-by: Dan Carpenter +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/sctp/ulpevent.h | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/include/net/sctp/ulpevent.h ++++ b/include/net/sctp/ulpevent.h +@@ -141,8 +141,12 @@ __u16 sctp_ulpevent_get_notification_typ + static inline int sctp_ulpevent_type_enabled(__u16 sn_type, + struct sctp_event_subscribe *mask) + { ++ int offset = sn_type - SCTP_SN_TYPE_BASE; + char *amask = (char *) mask; +- return amask[sn_type - SCTP_SN_TYPE_BASE]; ++ ++ if (offset >= sizeof(struct sctp_event_subscribe)) ++ return 0; ++ return amask[offset]; + } + + /* Given an event subscription, is this event enabled? */ diff --git a/queue-4.4/series b/queue-4.4/series index 7958056c941..6ac8130a92d 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -1,3 +1,19 @@ percpu-make-this_cpu_generic_read-atomic-w.r.t.-interrupts.patch drm-dp-mst-save-vcpi-with-payloads.patch mips-fix-minimum-alignment-requirement-of-irq-stack.patch +sctp-potential-read-out-of-bounds-in-sctp_ulpevent_type_enabled.patch +bpf-verifier-reject-bpf_alu64-bpf_end.patch +udpv6-fix-the-checksum-computation-when-hw-checksum-does-not-apply.patch +ip6_gre-skb_push-ipv6hdr-before-packing-the-header-in-ip6gre_header.patch +net-emac-fix-napi-poll-list-corruption.patch +packet-hold-bind-lock-when-rebinding-to-fanout-hook.patch +bpf-one-perf-event-close-won-t-free-bpf-program-attached-by-another-perf-event.patch +isdn-i4l-fetch-the-ppp_write-buffer-in-one-shot.patch +vti-fix-use-after-free-in-vti_tunnel_xmit-vti6_tnl_xmit.patch +l2tp-avoid-schedule-while-atomic-in-exit_net.patch +l2tp-fix-race-condition-in-l2tp_tunnel_delete.patch +tun-bail-out-from-tun_get_user-if-the-skb-is-empty.patch +packet-in-packet_do_bind-test-fanout-with-bind_lock-held.patch +packet-only-test-po-has_vnet_hdr-once-in-packet_snd.patch +net-set-sk_prot_creator-when-cloning-sockets-to-the-right-proto.patch +tipc-use-only-positive-error-codes-in-messages.patch diff --git a/queue-4.4/tipc-use-only-positive-error-codes-in-messages.patch b/queue-4.4/tipc-use-only-positive-error-codes-in-messages.patch new file mode 100644 index 00000000000..6a287d3024a --- /dev/null +++ b/queue-4.4/tipc-use-only-positive-error-codes-in-messages.patch @@ -0,0 +1,38 @@ +From foo@baz Thu Oct 19 14:05:19 CEST 2017 +From: Parthasarathy Bhuvaragan +Date: Fri, 29 Sep 2017 10:02:54 +0200 +Subject: tipc: use only positive error codes in messages + +From: Parthasarathy Bhuvaragan + + +[ Upstream commit aad06212d36cf34859428a0a279e5c14ee5c9e26 ] + +In commit e3a77561e7d32 ("tipc: split up function tipc_msg_eval()"), +we have updated the function tipc_msg_lookup_dest() to set the error +codes to negative values at destination lookup failures. Thus when +the function sets the error code to -TIPC_ERR_NO_NAME, its inserted +into the 4 bit error field of the message header as 0xf instead of +TIPC_ERR_NO_NAME (1). The value 0xf is an unknown error code. + +In this commit, we set only positive error code. + +Fixes: e3a77561e7d32 ("tipc: split up function tipc_msg_eval()") +Signed-off-by: Parthasarathy Bhuvaragan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/tipc/msg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/tipc/msg.c ++++ b/net/tipc/msg.c +@@ -541,7 +541,7 @@ bool tipc_msg_lookup_dest(struct net *ne + return false; + if (msg_errcode(msg)) + return false; +- *err = -TIPC_ERR_NO_NAME; ++ *err = TIPC_ERR_NO_NAME; + if (skb_linearize(skb)) + return false; + msg = buf_msg(skb); diff --git a/queue-4.4/tun-bail-out-from-tun_get_user-if-the-skb-is-empty.patch b/queue-4.4/tun-bail-out-from-tun_get_user-if-the-skb-is-empty.patch new file mode 100644 index 00000000000..d8abd552f90 --- /dev/null +++ b/queue-4.4/tun-bail-out-from-tun_get_user-if-the-skb-is-empty.patch @@ -0,0 +1,111 @@ +From foo@baz Thu Oct 19 14:05:19 CEST 2017 +From: Alexander Potapenko +Date: Thu, 28 Sep 2017 11:32:37 +0200 +Subject: tun: bail out from tun_get_user() if the skb is empty + +From: Alexander Potapenko + + +[ Upstream commit 2580c4c17aee3ad58e9751012bad278dd074ccae ] + +KMSAN (https://github.com/google/kmsan) reported accessing uninitialized +skb->data[0] in the case the skb is empty (i.e. skb->len is 0): + +================================================ +BUG: KMSAN: use of uninitialized memory in tun_get_user+0x19ba/0x3770 +CPU: 0 PID: 3051 Comm: probe Not tainted 4.13.0+ #3140 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 +Call Trace: +... + __msan_warning_32+0x66/0xb0 mm/kmsan/kmsan_instr.c:477 + tun_get_user+0x19ba/0x3770 drivers/net/tun.c:1301 + tun_chr_write_iter+0x19f/0x300 drivers/net/tun.c:1365 + call_write_iter ./include/linux/fs.h:1743 + new_sync_write fs/read_write.c:457 + __vfs_write+0x6c3/0x7f0 fs/read_write.c:470 + vfs_write+0x3e4/0x770 fs/read_write.c:518 + SYSC_write+0x12f/0x2b0 fs/read_write.c:565 + SyS_write+0x55/0x80 fs/read_write.c:557 + do_syscall_64+0x242/0x330 arch/x86/entry/common.c:284 + entry_SYSCALL64_slow_path+0x25/0x25 arch/x86/entry/entry_64.S:245 +... +origin: +... + kmsan_poison_shadow+0x6e/0xc0 mm/kmsan/kmsan.c:211 + slab_alloc_node mm/slub.c:2732 + __kmalloc_node_track_caller+0x351/0x370 mm/slub.c:4351 + __kmalloc_reserve net/core/skbuff.c:138 + __alloc_skb+0x26a/0x810 net/core/skbuff.c:231 + alloc_skb ./include/linux/skbuff.h:903 + alloc_skb_with_frags+0x1d7/0xc80 net/core/skbuff.c:4756 + sock_alloc_send_pskb+0xabf/0xfe0 net/core/sock.c:2037 + tun_alloc_skb drivers/net/tun.c:1144 + tun_get_user+0x9a8/0x3770 drivers/net/tun.c:1274 + tun_chr_write_iter+0x19f/0x300 drivers/net/tun.c:1365 + call_write_iter ./include/linux/fs.h:1743 + new_sync_write fs/read_write.c:457 + __vfs_write+0x6c3/0x7f0 fs/read_write.c:470 + vfs_write+0x3e4/0x770 fs/read_write.c:518 + SYSC_write+0x12f/0x2b0 fs/read_write.c:565 + SyS_write+0x55/0x80 fs/read_write.c:557 + do_syscall_64+0x242/0x330 arch/x86/entry/common.c:284 + return_from_SYSCALL_64+0x0/0x6a arch/x86/entry/entry_64.S:245 +================================================ + +Make sure tun_get_user() doesn't touch skb->data[0] unless there is +actual data. + +C reproducer below: +========================== + // autogenerated by syzkaller (http://github.com/google/syzkaller) + + #define _GNU_SOURCE + + #include + #include + #include + #include + #include + #include + + int main() + { + int sock = socket(PF_INET, SOCK_STREAM, IPPROTO_IP); + int tun_fd = open("/dev/net/tun", O_RDWR); + struct ifreq req; + memset(&req, 0, sizeof(struct ifreq)); + strcpy((char*)&req.ifr_name, "gre0"); + req.ifr_flags = IFF_UP | IFF_MULTICAST; + ioctl(tun_fd, TUNSETIFF, &req); + ioctl(sock, SIOCSIFFLAGS, "gre0"); + write(tun_fd, "hi", 0); + return 0; + } +========================== + +Signed-off-by: Alexander Potapenko +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/tun.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -1195,11 +1195,13 @@ static ssize_t tun_get_user(struct tun_s + switch (tun->flags & TUN_TYPE_MASK) { + case IFF_TUN: + if (tun->flags & IFF_NO_PI) { +- switch (skb->data[0] & 0xf0) { +- case 0x40: ++ u8 ip_version = skb->len ? (skb->data[0] >> 4) : 0; ++ ++ switch (ip_version) { ++ case 4: + pi.proto = htons(ETH_P_IP); + break; +- case 0x60: ++ case 6: + pi.proto = htons(ETH_P_IPV6); + break; + default: diff --git a/queue-4.4/udpv6-fix-the-checksum-computation-when-hw-checksum-does-not-apply.patch b/queue-4.4/udpv6-fix-the-checksum-computation-when-hw-checksum-does-not-apply.patch new file mode 100644 index 00000000000..e6239163202 --- /dev/null +++ b/queue-4.4/udpv6-fix-the-checksum-computation-when-hw-checksum-does-not-apply.patch @@ -0,0 +1,36 @@ +From foo@baz Thu Oct 19 14:05:19 CEST 2017 +From: Subash Abhinov Kasiviswanathan +Date: Wed, 13 Sep 2017 19:30:51 -0600 +Subject: udpv6: Fix the checksum computation when HW checksum does not apply + +From: Subash Abhinov Kasiviswanathan + + +[ Upstream commit 63ecc3d9436f8012e49dc846d6cb0a85a3433517 ] + +While trying an ESP transport mode encryption for UDPv6 packets of +datagram size 1436 with MTU 1500, checksum error was observed in +the secondary fragment. + +This error occurs due to the UDP payload checksum being missed out +when computing the full checksum for these packets in +udp6_hwcsum_outgoing(). + +Fixes: d39d938c8228 ("ipv6: Introduce udpv6_send_skb()") +Signed-off-by: Subash Abhinov Kasiviswanathan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/udp.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -1007,6 +1007,7 @@ static void udp6_hwcsum_outgoing(struct + */ + offset = skb_transport_offset(skb); + skb->csum = skb_checksum(skb, offset, skb->len - offset, 0); ++ csum = skb->csum; + + skb->ip_summed = CHECKSUM_NONE; + diff --git a/queue-4.4/vti-fix-use-after-free-in-vti_tunnel_xmit-vti6_tnl_xmit.patch b/queue-4.4/vti-fix-use-after-free-in-vti_tunnel_xmit-vti6_tnl_xmit.patch new file mode 100644 index 00000000000..6a3d14be4aa --- /dev/null +++ b/queue-4.4/vti-fix-use-after-free-in-vti_tunnel_xmit-vti6_tnl_xmit.patch @@ -0,0 +1,98 @@ +From foo@baz Thu Oct 19 14:05:19 CEST 2017 +From: Alexey Kodanev +Date: Tue, 26 Sep 2017 15:14:29 +0300 +Subject: vti: fix use after free in vti_tunnel_xmit/vti6_tnl_xmit + +From: Alexey Kodanev + + +[ Upstream commit 36f6ee22d2d66046e369757ec6bbe1c482957ba6 ] + +When running LTP IPsec tests, KASan might report: + +BUG: KASAN: use-after-free in vti_tunnel_xmit+0xeee/0xff0 [ip_vti] +Read of size 4 at addr ffff880dc6ad1980 by task swapper/0/0 +... +Call Trace: + + dump_stack+0x63/0x89 + print_address_description+0x7c/0x290 + kasan_report+0x28d/0x370 + ? vti_tunnel_xmit+0xeee/0xff0 [ip_vti] + __asan_report_load4_noabort+0x19/0x20 + vti_tunnel_xmit+0xeee/0xff0 [ip_vti] + ? vti_init_net+0x190/0x190 [ip_vti] + ? save_stack_trace+0x1b/0x20 + ? save_stack+0x46/0xd0 + dev_hard_start_xmit+0x147/0x510 + ? icmp_echo.part.24+0x1f0/0x210 + __dev_queue_xmit+0x1394/0x1c60 +... +Freed by task 0: + save_stack_trace+0x1b/0x20 + save_stack+0x46/0xd0 + kasan_slab_free+0x70/0xc0 + kmem_cache_free+0x81/0x1e0 + kfree_skbmem+0xb1/0xe0 + kfree_skb+0x75/0x170 + kfree_skb_list+0x3e/0x60 + __dev_queue_xmit+0x1298/0x1c60 + dev_queue_xmit+0x10/0x20 + neigh_resolve_output+0x3a8/0x740 + ip_finish_output2+0x5c0/0xe70 + ip_finish_output+0x4ba/0x680 + ip_output+0x1c1/0x3a0 + xfrm_output_resume+0xc65/0x13d0 + xfrm_output+0x1e4/0x380 + xfrm4_output_finish+0x5c/0x70 + +Can be fixed if we get skb->len before dst_output(). + +Fixes: b9959fd3b0fa ("vti: switch to new ip tunnel code") +Fixes: 22e1b23dafa8 ("vti6: Support inter address family tunneling.") +Signed-off-by: Alexey Kodanev +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/ip_vti.c | 3 ++- + net/ipv6/ip6_vti.c | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +--- a/net/ipv4/ip_vti.c ++++ b/net/ipv4/ip_vti.c +@@ -156,6 +156,7 @@ static netdev_tx_t vti_xmit(struct sk_bu + struct ip_tunnel_parm *parms = &tunnel->parms; + struct dst_entry *dst = skb_dst(skb); + struct net_device *tdev; /* Device to other host */ ++ int pkt_len = skb->len; + int err; + + if (!dst) { +@@ -199,7 +200,7 @@ static netdev_tx_t vti_xmit(struct sk_bu + + err = dst_output(tunnel->net, skb->sk, skb); + if (net_xmit_eval(err) == 0) +- err = skb->len; ++ err = pkt_len; + iptunnel_xmit_stats(err, &dev->stats, dev->tstats); + return NETDEV_TX_OK; + +--- a/net/ipv6/ip6_vti.c ++++ b/net/ipv6/ip6_vti.c +@@ -434,6 +434,7 @@ vti6_xmit(struct sk_buff *skb, struct ne + struct dst_entry *dst = skb_dst(skb); + struct net_device *tdev; + struct xfrm_state *x; ++ int pkt_len = skb->len; + int err = -1; + int mtu; + +@@ -487,7 +488,7 @@ vti6_xmit(struct sk_buff *skb, struct ne + struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats); + + u64_stats_update_begin(&tstats->syncp); +- tstats->tx_bytes += skb->len; ++ tstats->tx_bytes += pkt_len; + tstats->tx_packets++; + u64_stats_update_end(&tstats->syncp); + } else {