]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 23 Feb 2017 20:18:10 +0000 (21:18 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 23 Feb 2017 20:18:10 +0000 (21:18 +0100)
added patches:
ip-fix-ip_checksum-handling.patch
net-socket-fix-recvmmsg-not-returning-error-from-sock_error.patch
ptr_ring-fix-race-conditions-when-resizing.patch

queue-4.10/ip-fix-ip_checksum-handling.patch [new file with mode: 0644]
queue-4.10/net-socket-fix-recvmmsg-not-returning-error-from-sock_error.patch [new file with mode: 0644]
queue-4.10/ptr_ring-fix-race-conditions-when-resizing.patch [new file with mode: 0644]
queue-4.10/series [new file with mode: 0644]

diff --git a/queue-4.10/ip-fix-ip_checksum-handling.patch b/queue-4.10/ip-fix-ip_checksum-handling.patch
new file mode 100644 (file)
index 0000000..7f0228c
--- /dev/null
@@ -0,0 +1,49 @@
+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);
+ }
diff --git a/queue-4.10/net-socket-fix-recvmmsg-not-returning-error-from-sock_error.patch b/queue-4.10/net-socket-fix-recvmmsg-not-returning-error-from-sock_error.patch
new file mode 100644 (file)
index 0000000..6552d4f
--- /dev/null
@@ -0,0 +1,47 @@
+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;
diff --git a/queue-4.10/ptr_ring-fix-race-conditions-when-resizing.patch b/queue-4.10/ptr_ring-fix-race-conditions-when-resizing.patch
new file mode 100644 (file)
index 0000000..825160c
--- /dev/null
@@ -0,0 +1,135 @@
+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)
diff --git a/queue-4.10/series b/queue-4.10/series
new file mode 100644 (file)
index 0000000..6e39cb3
--- /dev/null
@@ -0,0 +1,3 @@
+ptr_ring-fix-race-conditions-when-resizing.patch
+ip-fix-ip_checksum-handling.patch
+net-socket-fix-recvmmsg-not-returning-error-from-sock_error.patch