From: Greg Kroah-Hartman Date: Thu, 23 Feb 2017 20:18:10 +0000 (+0100) Subject: 4.10-stable patches X-Git-Tag: v4.4.52~14 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7c407eb5818264c184ba7eb09f584152902ade16;p=thirdparty%2Fkernel%2Fstable-queue.git 4.10-stable patches 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 --- 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 index 00000000000..7f0228ccc42 --- /dev/null +++ b/queue-4.10/ip-fix-ip_checksum-handling.patch @@ -0,0 +1,49 @@ +From foo@baz Thu Feb 23 21:12:57 CET 2017 +From: Paolo Abeni +Date: Tue, 21 Feb 2017 09:33:18 +0100 +Subject: ip: fix IP_CHECKSUM handling + +From: Paolo Abeni + + +[ 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 +Signed-off-by: Paolo Abeni +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..6552d4f814c --- /dev/null +++ b/queue-4.10/net-socket-fix-recvmmsg-not-returning-error-from-sock_error.patch @@ -0,0 +1,47 @@ +From foo@baz Thu Feb 23 21:12:57 CET 2017 +From: Maxime Jayat +Date: Tue, 21 Feb 2017 18:35:51 +0100 +Subject: net: socket: fix recvmmsg not returning error from sock_error + +From: Maxime Jayat + + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..825160ce889 --- /dev/null +++ b/queue-4.10/ptr_ring-fix-race-conditions-when-resizing.patch @@ -0,0 +1,135 @@ +From foo@baz Thu Feb 23 21:12:57 CET 2017 +From: "Michael S. Tsirkin" +Date: Sun, 19 Feb 2017 07:17:17 +0200 +Subject: ptr_ring: fix race conditions when resizing + +From: "Michael S. Tsirkin" + + +[ 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); + + 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 +Cc: stable@vger.kernel.org +Cc: "David S. Miller" +Acked-by: Jason Wang +Signed-off-by: Michael S. Tsirkin +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..6e39cb3c4b3 --- /dev/null +++ b/queue-4.10/series @@ -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