--- /dev/null
+From foo@baz Thu Feb 23 21:12:57 CET 2017
+From: Paolo Abeni <pabeni@redhat.com>
+Date: Tue, 21 Feb 2017 09:33:18 +0100
+Subject: ip: fix IP_CHECKSUM handling
+
+From: Paolo Abeni <pabeni@redhat.com>
+
+
+[ Upstream commit ca4ef4574f1ee5252e2cd365f8f5d5bafd048f32 ]
+
+The skbs processed by ip_cmsg_recv() are not guaranteed to
+be linear e.g. when sending UDP packets over loopback with
+MSGMORE.
+Using csum_partial() on [potentially] the whole skb len
+is dangerous; instead be on the safe side and use skb_checksum().
+
+Thanks to syzkaller team to detect the issue and provide the
+reproducer.
+
+v1 -> v2:
+ - move the variable declaration in a tighter scope
+
+Fixes: ad6f939ab193 ("ip: Add offset parameter to ip_cmsg_recv")
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.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>
+---
+ net/ipv4/ip_sockglue.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/net/ipv4/ip_sockglue.c
++++ b/net/ipv4/ip_sockglue.c
+@@ -116,10 +116,10 @@ static void ip_cmsg_recv_checksum(struct
+ if (skb->ip_summed != CHECKSUM_COMPLETE)
+ return;
+
+- if (offset != 0)
+- csum = csum_sub(csum,
+- csum_partial(skb_transport_header(skb) + tlen,
+- offset, 0));
++ if (offset != 0) {
++ int tend_off = skb_transport_offset(skb) + tlen;
++ csum = csum_sub(csum, skb_checksum(skb, tend_off, offset, 0));
++ }
+
+ put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum);
+ }
--- /dev/null
+From foo@baz Thu Feb 23 21:12:57 CET 2017
+From: Maxime Jayat <maxime.jayat@mobile-devices.fr>
+Date: Tue, 21 Feb 2017 18:35:51 +0100
+Subject: net: socket: fix recvmmsg not returning error from sock_error
+
+From: Maxime Jayat <maxime.jayat@mobile-devices.fr>
+
+
+[ Upstream commit e623a9e9dec29ae811d11f83d0074ba254aba374 ]
+
+Commit 34b88a68f26a ("net: Fix use after free in the recvmmsg exit path"),
+changed the exit path of recvmmsg to always return the datagrams
+variable and modified the error paths to set the variable to the error
+code returned by recvmsg if necessary.
+
+However in the case sock_error returned an error, the error code was
+then ignored, and recvmmsg returned 0.
+
+Change the error path of recvmmsg to correctly return the error code
+of sock_error.
+
+The bug was triggered by using recvmmsg on a CAN interface which was
+not up. Linux 4.6 and later return 0 in this case while earlier
+releases returned -ENETDOWN.
+
+Fixes: 34b88a68f26a ("net: Fix use after free in the recvmmsg exit path")
+Signed-off-by: Maxime Jayat <maxime.jayat@mobile-devices.fr>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/socket.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -2228,8 +2228,10 @@ int __sys_recvmmsg(int fd, struct mmsghd
+ return err;
+
+ err = sock_error(sock->sk);
+- if (err)
++ if (err) {
++ datagrams = err;
+ goto out_put;
++ }
+
+ entry = mmsg;
+ compat_entry = (struct compat_mmsghdr __user *)mmsg;
--- /dev/null
+From foo@baz Thu Feb 23 21:12:57 CET 2017
+From: "Michael S. Tsirkin" <mst@redhat.com>
+Date: Sun, 19 Feb 2017 07:17:17 +0200
+Subject: ptr_ring: fix race conditions when resizing
+
+From: "Michael S. Tsirkin" <mst@redhat.com>
+
+
+[ Upstream commit e71695307114335be1ed912f4a347396c2ed0e69 ]
+
+Resizing currently drops consumer lock. This can cause entries to be
+reordered, which isn't good in itself. More importantly, consumer can
+detect a false ring empty condition and block forever.
+
+Further, nesting of consumer within producer lock is problematic for
+tun, since it produces entries in a BH, which causes a lock order
+reversal:
+
+ CPU0 CPU1
+ ---- ----
+ consume:
+ lock(&(&r->consumer_lock)->rlock);
+ resize:
+ local_irq_disable();
+ lock(&(&r->producer_lock)->rlock);
+ lock(&(&r->consumer_lock)->rlock);
+ <Interrupt>
+ produce:
+ lock(&(&r->producer_lock)->rlock);
+
+To fix, nest producer lock within consumer lock during resize,
+and keep consumer lock during the whole swap operation.
+
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Cc: stable@vger.kernel.org
+Cc: "David S. Miller" <davem@davemloft.net>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/ptr_ring.h | 36 +++++++++++++++++++++++++++++++-----
+ 1 file changed, 31 insertions(+), 5 deletions(-)
+
+--- a/include/linux/ptr_ring.h
++++ b/include/linux/ptr_ring.h
+@@ -111,6 +111,11 @@ static inline int __ptr_ring_produce(str
+ return 0;
+ }
+
++/*
++ * Note: resize (below) nests producer lock within consumer lock, so if you
++ * consume in interrupt or BH context, you must disable interrupts/BH when
++ * calling this.
++ */
+ static inline int ptr_ring_produce(struct ptr_ring *r, void *ptr)
+ {
+ int ret;
+@@ -242,6 +247,11 @@ static inline void *__ptr_ring_consume(s
+ return ptr;
+ }
+
++/*
++ * Note: resize (below) nests producer lock within consumer lock, so if you
++ * call this in interrupt or BH context, you must disable interrupts/BH when
++ * producing.
++ */
+ static inline void *ptr_ring_consume(struct ptr_ring *r)
+ {
+ void *ptr;
+@@ -357,7 +367,7 @@ static inline void **__ptr_ring_swap_que
+ void **old;
+ void *ptr;
+
+- while ((ptr = ptr_ring_consume(r)))
++ while ((ptr = __ptr_ring_consume(r)))
+ if (producer < size)
+ queue[producer++] = ptr;
+ else if (destroy)
+@@ -372,6 +382,12 @@ static inline void **__ptr_ring_swap_que
+ return old;
+ }
+
++/*
++ * Note: producer lock is nested within consumer lock, so if you
++ * resize you must make sure all uses nest correctly.
++ * In particular if you consume ring in interrupt or BH context, you must
++ * disable interrupts/BH when doing so.
++ */
+ static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp,
+ void (*destroy)(void *))
+ {
+@@ -382,17 +398,25 @@ static inline int ptr_ring_resize(struct
+ if (!queue)
+ return -ENOMEM;
+
+- spin_lock_irqsave(&(r)->producer_lock, flags);
++ spin_lock_irqsave(&(r)->consumer_lock, flags);
++ spin_lock(&(r)->producer_lock);
+
+ old = __ptr_ring_swap_queue(r, queue, size, gfp, destroy);
+
+- spin_unlock_irqrestore(&(r)->producer_lock, flags);
++ spin_unlock(&(r)->producer_lock);
++ spin_unlock_irqrestore(&(r)->consumer_lock, flags);
+
+ kfree(old);
+
+ return 0;
+ }
+
++/*
++ * Note: producer lock is nested within consumer lock, so if you
++ * resize you must make sure all uses nest correctly.
++ * In particular if you consume ring in interrupt or BH context, you must
++ * disable interrupts/BH when doing so.
++ */
+ static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, int nrings,
+ int size,
+ gfp_t gfp, void (*destroy)(void *))
+@@ -412,10 +436,12 @@ static inline int ptr_ring_resize_multip
+ }
+
+ for (i = 0; i < nrings; ++i) {
+- spin_lock_irqsave(&(rings[i])->producer_lock, flags);
++ spin_lock_irqsave(&(rings[i])->consumer_lock, flags);
++ spin_lock(&(rings[i])->producer_lock);
+ queues[i] = __ptr_ring_swap_queue(rings[i], queues[i],
+ size, gfp, destroy);
+- spin_unlock_irqrestore(&(rings[i])->producer_lock, flags);
++ spin_unlock(&(rings[i])->producer_lock);
++ spin_unlock_irqrestore(&(rings[i])->consumer_lock, flags);
+ }
+
+ for (i = 0; i < nrings; ++i)