From: Greg Kroah-Hartman Date: Tue, 3 Nov 2020 16:03:59 +0000 (+0100) Subject: 4.4-stable patches X-Git-Tag: v4.14.204~23 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e1ac1d17eed079bfcbde9098af65f31ebf544096;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: 9p-cast-to-loff_t-before-multiplying.patch ceph-promote-to-unsigned-long-long-before-shifting.patch ext4-fix-superblock-checksum-calculation-race.patch libceph-clear-con-out_msg-on-policy-stateful_server-faults.patch ring-buffer-return-0-on-success-from-ring_buffer_resize.patch vringh-fix-__vringh_iov-when-riov-and-wiov-are-different.patch --- diff --git a/queue-4.4/9p-cast-to-loff_t-before-multiplying.patch b/queue-4.4/9p-cast-to-loff_t-before-multiplying.patch new file mode 100644 index 00000000000..e44fb2f0c43 --- /dev/null +++ b/queue-4.4/9p-cast-to-loff_t-before-multiplying.patch @@ -0,0 +1,37 @@ +From f5f7ab168b9a60e12a4b8f2bb6fcc91321dc23c1 Mon Sep 17 00:00:00 2001 +From: "Matthew Wilcox (Oracle)" +Date: Sun, 4 Oct 2020 19:04:22 +0100 +Subject: 9P: Cast to loff_t before multiplying + +From: Matthew Wilcox (Oracle) + +commit f5f7ab168b9a60e12a4b8f2bb6fcc91321dc23c1 upstream. + +On 32-bit systems, this multiplication will overflow for files larger +than 4GB. + +Link: http://lkml.kernel.org/r/20201004180428.14494-2-willy@infradead.org +Cc: stable@vger.kernel.org +Fixes: fb89b45cdfdc ("9P: introduction of a new cache=mmap model.") +Signed-off-by: Matthew Wilcox (Oracle) +Signed-off-by: Dominique Martinet +Signed-off-by: Greg Kroah-Hartman + +--- + fs/9p/vfs_file.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/9p/vfs_file.c ++++ b/fs/9p/vfs_file.c +@@ -624,9 +624,9 @@ static void v9fs_mmap_vm_close(struct vm + struct writeback_control wbc = { + .nr_to_write = LONG_MAX, + .sync_mode = WB_SYNC_ALL, +- .range_start = vma->vm_pgoff * PAGE_SIZE, ++ .range_start = (loff_t)vma->vm_pgoff * PAGE_SIZE, + /* absolute end, byte at end included */ +- .range_end = vma->vm_pgoff * PAGE_SIZE + ++ .range_end = (loff_t)vma->vm_pgoff * PAGE_SIZE + + (vma->vm_end - vma->vm_start - 1), + }; + diff --git a/queue-4.4/ceph-promote-to-unsigned-long-long-before-shifting.patch b/queue-4.4/ceph-promote-to-unsigned-long-long-before-shifting.patch new file mode 100644 index 00000000000..2d2e33728a0 --- /dev/null +++ b/queue-4.4/ceph-promote-to-unsigned-long-long-before-shifting.patch @@ -0,0 +1,33 @@ +From c403c3a2fbe24d4ed33e10cabad048583ebd4edf Mon Sep 17 00:00:00 2001 +From: "Matthew Wilcox (Oracle)" +Date: Sun, 4 Oct 2020 19:04:24 +0100 +Subject: ceph: promote to unsigned long long before shifting + +From: Matthew Wilcox (Oracle) + +commit c403c3a2fbe24d4ed33e10cabad048583ebd4edf upstream. + +On 32-bit systems, this shift will overflow for files larger than 4GB. + +Cc: stable@vger.kernel.org +Fixes: 61f68816211e ("ceph: check caps in filemap_fault and page_mkwrite") +Signed-off-by: Matthew Wilcox (Oracle) +Reviewed-by: Jeff Layton +Signed-off-by: Ilya Dryomov +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ceph/addr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ceph/addr.c ++++ b/fs/ceph/addr.c +@@ -1243,7 +1243,7 @@ static int ceph_filemap_fault(struct vm_ + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_file_info *fi = vma->vm_file->private_data; + struct page *pinned_page = NULL; +- loff_t off = vmf->pgoff << PAGE_CACHE_SHIFT; ++ loff_t off = (loff_t)vmf->pgoff << PAGE_CACHE_SHIFT; + int want, got, ret; + + dout("filemap_fault %p %llx.%llx %llu~%zd trying to get caps\n", diff --git a/queue-4.4/ext4-fix-superblock-checksum-calculation-race.patch b/queue-4.4/ext4-fix-superblock-checksum-calculation-race.patch new file mode 100644 index 00000000000..e0f80b66195 --- /dev/null +++ b/queue-4.4/ext4-fix-superblock-checksum-calculation-race.patch @@ -0,0 +1,60 @@ +From acaa532687cdc3a03757defafece9c27aa667546 Mon Sep 17 00:00:00 2001 +From: Constantine Sapuntzakis +Date: Mon, 14 Sep 2020 10:10:14 -0600 +Subject: ext4: fix superblock checksum calculation race + +From: Constantine Sapuntzakis + +commit acaa532687cdc3a03757defafece9c27aa667546 upstream. + +The race condition could cause the persisted superblock checksum +to not match the contents of the superblock, causing the +superblock to be considered corrupt. + +An example of the race follows. A first thread is interrupted in the +middle of a checksum calculation. Then, another thread changes the +superblock, calculates a new checksum, and sets it. Then, the first +thread resumes and sets the checksum based on the older superblock. + +To fix, serialize the superblock checksum calculation using the buffer +header lock. While a spinlock is sufficient, the buffer header is +already there and there is precedent for locking it (e.g. in +ext4_commit_super). + +Tested the patch by booting up a kernel with the patch, creating +a filesystem and some files (including some orphans), and then +unmounting and remounting the file system. + +Cc: stable@kernel.org +Signed-off-by: Constantine Sapuntzakis +Reviewed-by: Jan Kara +Suggested-by: Jan Kara +Link: https://lore.kernel.org/r/20200914161014.22275-1-costa@purestorage.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -144,7 +144,18 @@ void ext4_superblock_csum_set(struct sup + if (!ext4_has_metadata_csum(sb)) + return; + ++ /* ++ * Locking the superblock prevents the scenario ++ * where: ++ * 1) a first thread pauses during checksum calculation. ++ * 2) a second thread updates the superblock, recalculates ++ * the checksum, and updates s_checksum ++ * 3) the first thread resumes and finishes its checksum calculation ++ * and updates s_checksum with a potentially stale or torn value. ++ */ ++ lock_buffer(EXT4_SB(sb)->s_sbh); + es->s_checksum = ext4_superblock_csum(sb, es); ++ unlock_buffer(EXT4_SB(sb)->s_sbh); + } + + void *ext4_kvmalloc(size_t size, gfp_t flags) diff --git a/queue-4.4/libceph-clear-con-out_msg-on-policy-stateful_server-faults.patch b/queue-4.4/libceph-clear-con-out_msg-on-policy-stateful_server-faults.patch new file mode 100644 index 00000000000..65184d31d52 --- /dev/null +++ b/queue-4.4/libceph-clear-con-out_msg-on-policy-stateful_server-faults.patch @@ -0,0 +1,57 @@ +From 28e1581c3b4ea5f98530064a103c6217bedeea73 Mon Sep 17 00:00:00 2001 +From: Ilya Dryomov +Date: Wed, 7 Oct 2020 20:06:48 +0200 +Subject: libceph: clear con->out_msg on Policy::stateful_server faults + +From: Ilya Dryomov + +commit 28e1581c3b4ea5f98530064a103c6217bedeea73 upstream. + +con->out_msg must be cleared on Policy::stateful_server +(!CEPH_MSG_CONNECT_LOSSY) faults. Not doing so botches the +reconnection attempt, because after writing the banner the +messenger moves on to writing the data section of that message +(either from where it got interrupted by the connection reset or +from the beginning) instead of writing struct ceph_msg_connect. +This results in a bizarre error message because the server +sends CEPH_MSGR_TAG_BADPROTOVER but we think we wrote struct +ceph_msg_connect: + + libceph: mds0 (1)172.21.15.45:6828 socket error on write + ceph: mds0 reconnect start + libceph: mds0 (1)172.21.15.45:6829 socket closed (con state OPEN) + libceph: mds0 (1)172.21.15.45:6829 protocol version mismatch, my 32 != server's 32 + libceph: mds0 (1)172.21.15.45:6829 protocol version mismatch + +AFAICT this bug goes back to the dawn of the kernel client. +The reason it survived for so long is that only MDS sessions +are stateful and only two MDS messages have a data section: +CEPH_MSG_CLIENT_RECONNECT (always, but reconnecting is rare) +and CEPH_MSG_CLIENT_REQUEST (only when xattrs are involved). +The connection has to get reset precisely when such message +is being sent -- in this case it was the former. + +Cc: stable@vger.kernel.org +Link: https://tracker.ceph.com/issues/47723 +Signed-off-by: Ilya Dryomov +Reviewed-by: Jeff Layton +Signed-off-by: Greg Kroah-Hartman + +--- + net/ceph/messenger.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/net/ceph/messenger.c ++++ b/net/ceph/messenger.c +@@ -2976,6 +2976,11 @@ static void con_fault(struct ceph_connec + ceph_msg_put(con->in_msg); + con->in_msg = NULL; + } ++ if (con->out_msg) { ++ BUG_ON(con->out_msg->con != con); ++ ceph_msg_put(con->out_msg); ++ con->out_msg = NULL; ++ } + + /* Requeue anything that hasn't been acked */ + list_splice_init(&con->out_sent, &con->out_queue); diff --git a/queue-4.4/ring-buffer-return-0-on-success-from-ring_buffer_resize.patch b/queue-4.4/ring-buffer-return-0-on-success-from-ring_buffer_resize.patch new file mode 100644 index 00000000000..d45161320e7 --- /dev/null +++ b/queue-4.4/ring-buffer-return-0-on-success-from-ring_buffer_resize.patch @@ -0,0 +1,64 @@ +From 0a1754b2a97efa644aa6e84d1db5b17c42251483 Mon Sep 17 00:00:00 2001 +From: Qiujun Huang +Date: Mon, 19 Oct 2020 22:22:42 +0800 +Subject: ring-buffer: Return 0 on success from ring_buffer_resize() + +From: Qiujun Huang + +commit 0a1754b2a97efa644aa6e84d1db5b17c42251483 upstream. + +We don't need to check the new buffer size, and the return value +had confused resize_buffer_duplicate_size(). +... + ret = ring_buffer_resize(trace_buf->buffer, + per_cpu_ptr(size_buf->data,cpu_id)->entries, cpu_id); + if (ret == 0) + per_cpu_ptr(trace_buf->data, cpu_id)->entries = + per_cpu_ptr(size_buf->data, cpu_id)->entries; +... + +Link: https://lkml.kernel.org/r/20201019142242.11560-1-hqjagain@gmail.com + +Cc: stable@vger.kernel.org +Fixes: d60da506cbeb3 ("tracing: Add a resize function to make one buffer equivalent to another buffer") +Signed-off-by: Qiujun Huang +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/trace/ring_buffer.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -1659,18 +1659,18 @@ int ring_buffer_resize(struct ring_buffe + { + struct ring_buffer_per_cpu *cpu_buffer; + unsigned long nr_pages; +- int cpu, err = 0; ++ int cpu, err; + + /* + * Always succeed at resizing a non-existent buffer: + */ + if (!buffer) +- return size; ++ return 0; + + /* Make sure the requested buffer exists */ + if (cpu_id != RING_BUFFER_ALL_CPUS && + !cpumask_test_cpu(cpu_id, buffer->cpumask)) +- return size; ++ return 0; + + nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE); + +@@ -1810,7 +1810,7 @@ int ring_buffer_resize(struct ring_buffe + } + + mutex_unlock(&buffer->mutex); +- return size; ++ return 0; + + out_err: + for_each_buffer_cpu(buffer, cpu) { diff --git a/queue-4.4/series b/queue-4.4/series index 476702f1fa0..8c93c80705c 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -49,3 +49,9 @@ powerpc-powernv-elog-fix-race-while-processing-opal-error-log-event.patch ubifs-dent-fix-some-potential-memory-leaks-while-iterating-entries.patch ubi-check-kthread_should_stop-after-the-setting-of-task-state.patch ia64-fix-build-error-with-coredump.patch +ceph-promote-to-unsigned-long-long-before-shifting.patch +libceph-clear-con-out_msg-on-policy-stateful_server-faults.patch +9p-cast-to-loff_t-before-multiplying.patch +ring-buffer-return-0-on-success-from-ring_buffer_resize.patch +vringh-fix-__vringh_iov-when-riov-and-wiov-are-different.patch +ext4-fix-superblock-checksum-calculation-race.patch diff --git a/queue-4.4/vringh-fix-__vringh_iov-when-riov-and-wiov-are-different.patch b/queue-4.4/vringh-fix-__vringh_iov-when-riov-and-wiov-are-different.patch new file mode 100644 index 00000000000..61934ff1c6d --- /dev/null +++ b/queue-4.4/vringh-fix-__vringh_iov-when-riov-and-wiov-are-different.patch @@ -0,0 +1,58 @@ +From 5745bcfbbf89b158416075374254d3c013488f21 Mon Sep 17 00:00:00 2001 +From: Stefano Garzarella +Date: Thu, 8 Oct 2020 22:42:56 +0200 +Subject: vringh: fix __vringh_iov() when riov and wiov are different + +From: Stefano Garzarella + +commit 5745bcfbbf89b158416075374254d3c013488f21 upstream. + +If riov and wiov are both defined and they point to different +objects, only riov is initialized. If the wiov is not initialized +by the caller, the function fails returning -EINVAL and printing +"Readable desc 0x... after writable" error message. + +This issue happens when descriptors have both readable and writable +buffers (eg. virtio-blk devices has virtio_blk_outhdr in the readable +buffer and status as last byte of writable buffer) and we call +__vringh_iov() to get both type of buffers in two different iovecs. + +Let's replace the 'else if' clause with 'if' to initialize both +riov and wiov if they are not NULL. + +As checkpatch pointed out, we also avoid crashing the kernel +when riov and wiov are both NULL, replacing BUG() with WARN_ON() +and returning -EINVAL. + +Fixes: f87d0fbb5798 ("vringh: host-side implementation of virtio rings.") +Cc: stable@vger.kernel.org +Signed-off-by: Stefano Garzarella +Link: https://lore.kernel.org/r/20201008204256.162292-1-sgarzare@redhat.com +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/vhost/vringh.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/vhost/vringh.c ++++ b/drivers/vhost/vringh.c +@@ -272,13 +272,14 @@ __vringh_iov(struct vringh *vrh, u16 i, + desc_max = vrh->vring.num; + up_next = -1; + ++ /* You must want something! */ ++ if (WARN_ON(!riov && !wiov)) ++ return -EINVAL; ++ + if (riov) + riov->i = riov->used = 0; +- else if (wiov) ++ if (wiov) + wiov->i = wiov->used = 0; +- else +- /* You must want something! */ +- BUG(); + + for (;;) { + void *addr;