]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 27 Jan 2024 00:57:05 +0000 (16:57 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 27 Jan 2024 00:57:05 +0000 (16:57 -0800)
added patches:
kvm-use-__vcalloc-for-very-large-allocations.patch
mm-vmalloc-introduce-array-allocation-functions.patch
smb3-replace-smb2pdu-1-element-arrays-with-flex-arrays.patch
stddef-introduce-declare_flex_array-helper.patch

queue-5.10/kvm-use-__vcalloc-for-very-large-allocations.patch [new file with mode: 0644]
queue-5.10/mm-page_alloc-unreserve-highatomic-page-blocks-before-oom.patch [deleted file]
queue-5.10/mm-vmalloc-introduce-array-allocation-functions.patch [new file with mode: 0644]
queue-5.10/series
queue-5.10/smb3-replace-smb2pdu-1-element-arrays-with-flex-arrays.patch [new file with mode: 0644]
queue-5.10/stddef-introduce-declare_flex_array-helper.patch [new file with mode: 0644]

diff --git a/queue-5.10/kvm-use-__vcalloc-for-very-large-allocations.patch b/queue-5.10/kvm-use-__vcalloc-for-very-large-allocations.patch
new file mode 100644 (file)
index 0000000..6152a96
--- /dev/null
@@ -0,0 +1,81 @@
+From 37b2a6510a48ca361ced679f92682b7b7d7d0330 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Tue, 8 Mar 2022 04:49:37 -0500
+Subject: KVM: use __vcalloc for very large allocations
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+commit 37b2a6510a48ca361ced679f92682b7b7d7d0330 upstream.
+
+Allocations whose size is related to the memslot size can be arbitrarily
+large.  Do not use kvzalloc/kvcalloc, as those are limited to "not crazy"
+sizes that fit in 32 bits.
+
+Cc: stable@vger.kernel.org
+Fixes: 7661809d493b ("mm: don't allow oversized kvmalloc() calls")
+Reviewed-by: David Hildenbrand <david@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Alexander Ofitserov <oficerovas@altlinux.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/powerpc/kvm/book3s_hv_uvmem.c |    2 +-
+ arch/x86/kvm/mmu/page_track.c      |    2 +-
+ arch/x86/kvm/x86.c                 |    4 ++--
+ virt/kvm/kvm_main.c                |    4 ++--
+ 4 files changed, 6 insertions(+), 6 deletions(-)
+
+--- a/arch/powerpc/kvm/book3s_hv_uvmem.c
++++ b/arch/powerpc/kvm/book3s_hv_uvmem.c
+@@ -250,7 +250,7 @@ int kvmppc_uvmem_slot_init(struct kvm *k
+       p = kzalloc(sizeof(*p), GFP_KERNEL);
+       if (!p)
+               return -ENOMEM;
+-      p->pfns = vzalloc(array_size(slot->npages, sizeof(*p->pfns)));
++      p->pfns = vcalloc(slot->npages, sizeof(*p->pfns));
+       if (!p->pfns) {
+               kfree(p);
+               return -ENOMEM;
+--- a/arch/x86/kvm/mmu/page_track.c
++++ b/arch/x86/kvm/mmu/page_track.c
+@@ -35,7 +35,7 @@ int kvm_page_track_create_memslot(struct
+       for (i = 0; i < KVM_PAGE_TRACK_MAX; i++) {
+               slot->arch.gfn_track[i] =
+-                      kvcalloc(npages, sizeof(*slot->arch.gfn_track[i]),
++                      __vcalloc(npages, sizeof(*slot->arch.gfn_track[i]),
+                                GFP_KERNEL_ACCOUNT);
+               if (!slot->arch.gfn_track[i])
+                       goto track_free;
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -10826,14 +10826,14 @@ static int kvm_alloc_memslot_metadata(st
+                                     slot->base_gfn, level) + 1;
+               slot->arch.rmap[i] =
+-                      kvcalloc(lpages, sizeof(*slot->arch.rmap[i]),
++                      __vcalloc(lpages, sizeof(*slot->arch.rmap[i]),
+                                GFP_KERNEL_ACCOUNT);
+               if (!slot->arch.rmap[i])
+                       goto out_free;
+               if (i == 0)
+                       continue;
+-              linfo = kvcalloc(lpages, sizeof(*linfo), GFP_KERNEL_ACCOUNT);
++              linfo = __vcalloc(lpages, sizeof(*linfo), GFP_KERNEL_ACCOUNT);
+               if (!linfo)
+                       goto out_free;
+--- a/virt/kvm/kvm_main.c
++++ b/virt/kvm/kvm_main.c
+@@ -1008,9 +1008,9 @@ static int kvm_vm_release(struct inode *
+  */
+ static int kvm_alloc_dirty_bitmap(struct kvm_memory_slot *memslot)
+ {
+-      unsigned long dirty_bytes = 2 * kvm_dirty_bitmap_bytes(memslot);
++      unsigned long dirty_bytes = kvm_dirty_bitmap_bytes(memslot);
+-      memslot->dirty_bitmap = kvzalloc(dirty_bytes, GFP_KERNEL_ACCOUNT);
++      memslot->dirty_bitmap = __vcalloc(2, dirty_bytes, GFP_KERNEL_ACCOUNT);
+       if (!memslot->dirty_bitmap)
+               return -ENOMEM;
diff --git a/queue-5.10/mm-page_alloc-unreserve-highatomic-page-blocks-before-oom.patch b/queue-5.10/mm-page_alloc-unreserve-highatomic-page-blocks-before-oom.patch
deleted file mode 100644 (file)
index e209541..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-From ac3f3b0a55518056bc80ed32a41931c99e1f7d81 Mon Sep 17 00:00:00 2001
-From: Charan Teja Kalla <quic_charante@quicinc.com>
-Date: Fri, 24 Nov 2023 16:27:25 +0530
-Subject: mm: page_alloc: unreserve highatomic page blocks before oom
-
-From: Charan Teja Kalla <quic_charante@quicinc.com>
-
-commit ac3f3b0a55518056bc80ed32a41931c99e1f7d81 upstream.
-
-__alloc_pages_direct_reclaim() is called from slowpath allocation where
-high atomic reserves can be unreserved after there is a progress in
-reclaim and yet no suitable page is found.  Later should_reclaim_retry()
-gets called from slow path allocation to decide if the reclaim needs to be
-retried before OOM kill path is taken.
-
-should_reclaim_retry() checks the available(reclaimable + free pages)
-memory against the min wmark levels of a zone and returns:
-
-a) true, if it is above the min wmark so that slow path allocation will
-   do the reclaim retries.
-
-b) false, thus slowpath allocation takes oom kill path.
-
-should_reclaim_retry() can also unreserves the high atomic reserves **but
-only after all the reclaim retries are exhausted.**
-
-In a case where there are almost none reclaimable memory and free pages
-contains mostly the high atomic reserves but allocation context can't use
-these high atomic reserves, makes the available memory below min wmark
-levels hence false is returned from should_reclaim_retry() leading the
-allocation request to take OOM kill path.  This can turn into a early oom
-kill if high atomic reserves are holding lot of free memory and
-unreserving of them is not attempted.
-
-(early)OOM is encountered on a VM with the below state:
-[  295.998653] Normal free:7728kB boost:0kB min:804kB low:1004kB
-high:1204kB reserved_highatomic:8192KB active_anon:4kB inactive_anon:0kB
-active_file:24kB inactive_file:24kB unevictable:1220kB writepending:0kB
-present:70732kB managed:49224kB mlocked:0kB bounce:0kB free_pcp:688kB
-local_pcp:492kB free_cma:0kB
-[  295.998656] lowmem_reserve[]: 0 32
-[  295.998659] Normal: 508*4kB (UMEH) 241*8kB (UMEH) 143*16kB (UMEH)
-33*32kB (UH) 7*64kB (UH) 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB
-0*4096kB = 7752kB
-
-Per above log, the free memory of ~7MB exist in the high atomic reserves
-is not freed up before falling back to oom kill path.
-
-Fix it by trying to unreserve the high atomic reserves in
-should_reclaim_retry() before __alloc_pages_direct_reclaim() can fallback
-to oom kill path.
-
-Link: https://lkml.kernel.org/r/1700823445-27531-1-git-send-email-quic_charante@quicinc.com
-Fixes: 0aaa29a56e4f ("mm, page_alloc: reserve pageblocks for high-order atomic allocations on demand")
-Signed-off-by: Charan Teja Kalla <quic_charante@quicinc.com>
-Reported-by: Chris Goldsworthy <quic_cgoldswo@quicinc.com>
-Suggested-by: Michal Hocko <mhocko@suse.com>
-Acked-by: Michal Hocko <mhocko@suse.com>
-Acked-by: David Rientjes <rientjes@google.com>
-Cc: Chris Goldsworthy <quic_cgoldswo@quicinc.com>
-Cc: David Hildenbrand <david@redhat.com>
-Cc: Johannes Weiner <hannes@cmpxchg.org>
-Cc: Mel Gorman <mgorman@techsingularity.net>
-Cc: Pavankumar Kondeti <quic_pkondeti@quicinc.com>
-Cc: Vlastimil Babka <vbabka@suse.cz>
-Cc: Joakim Tjernlund <Joakim.Tjernlund@infinera.com>
-Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- mm/page_alloc.c |   16 ++++++++--------
- 1 file changed, 8 insertions(+), 8 deletions(-)
-
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -4534,14 +4534,9 @@ should_reclaim_retry(gfp_t gfp_mask, uns
-       else
-               (*no_progress_loops)++;
--      /*
--       * Make sure we converge to OOM if we cannot make any progress
--       * several times in the row.
--       */
--      if (*no_progress_loops > MAX_RECLAIM_RETRIES) {
--              /* Before OOM, exhaust highatomic_reserve */
--              return unreserve_highatomic_pageblock(ac, true);
--      }
-+      if (*no_progress_loops > MAX_RECLAIM_RETRIES)
-+              goto out;
-+
-       /*
-        * Keep reclaiming pages while there is a chance this will lead
-@@ -4603,6 +4598,11 @@ out:
-               schedule_timeout_uninterruptible(1);
-       else
-               cond_resched();
-+out:
-+      /* Before OOM, exhaust highatomic_reserve */
-+      if (!ret)
-+              return unreserve_highatomic_pageblock(ac, true);
-+
-       return ret;
- }
diff --git a/queue-5.10/mm-vmalloc-introduce-array-allocation-functions.patch b/queue-5.10/mm-vmalloc-introduce-array-allocation-functions.patch
new file mode 100644 (file)
index 0000000..76efe5c
--- /dev/null
@@ -0,0 +1,96 @@
+From a8749a35c39903120ec421ef2525acc8e0daa55c Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Tue, 8 Mar 2022 04:47:22 -0500
+Subject: mm: vmalloc: introduce array allocation functions
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+commit a8749a35c39903120ec421ef2525acc8e0daa55c upstream.
+
+Linux has dozens of occurrences of vmalloc(array_size()) and
+vzalloc(array_size()).  Allow to simplify the code by providing
+vmalloc_array and vcalloc, as well as the underscored variants that let
+the caller specify the GFP flags.
+
+Acked-by: Michal Hocko <mhocko@suse.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Alexander Ofitserov <oficerovas@altlinux.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/vmalloc.h |    5 ++++
+ mm/util.c               |   50 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 55 insertions(+)
+
+--- a/include/linux/vmalloc.h
++++ b/include/linux/vmalloc.h
+@@ -112,6 +112,11 @@ extern void *__vmalloc_node_range(unsign
+ void *__vmalloc_node(unsigned long size, unsigned long align, gfp_t gfp_mask,
+               int node, const void *caller);
++extern void *__vmalloc_array(size_t n, size_t size, gfp_t flags) __alloc_size(1, 2);
++extern void *vmalloc_array(size_t n, size_t size) __alloc_size(1, 2);
++extern void *__vcalloc(size_t n, size_t size, gfp_t flags) __alloc_size(1, 2);
++extern void *vcalloc(size_t n, size_t size) __alloc_size(1, 2);
++
+ extern void vfree(const void *addr);
+ extern void vfree_atomic(const void *addr);
+--- a/mm/util.c
++++ b/mm/util.c
+@@ -686,6 +686,56 @@ static inline void *__page_rmapping(stru
+       return (void *)mapping;
+ }
++/**
++ * __vmalloc_array - allocate memory for a virtually contiguous array.
++ * @n: number of elements.
++ * @size: element size.
++ * @flags: the type of memory to allocate (see kmalloc).
++ */
++void *__vmalloc_array(size_t n, size_t size, gfp_t flags)
++{
++      size_t bytes;
++
++      if (unlikely(check_mul_overflow(n, size, &bytes)))
++              return NULL;
++      return __vmalloc(bytes, flags);
++}
++EXPORT_SYMBOL(__vmalloc_array);
++
++/**
++ * vmalloc_array - allocate memory for a virtually contiguous array.
++ * @n: number of elements.
++ * @size: element size.
++ */
++void *vmalloc_array(size_t n, size_t size)
++{
++      return __vmalloc_array(n, size, GFP_KERNEL);
++}
++EXPORT_SYMBOL(vmalloc_array);
++
++/**
++ * __vcalloc - allocate and zero memory for a virtually contiguous array.
++ * @n: number of elements.
++ * @size: element size.
++ * @flags: the type of memory to allocate (see kmalloc).
++ */
++void *__vcalloc(size_t n, size_t size, gfp_t flags)
++{
++      return __vmalloc_array(n, size, flags | __GFP_ZERO);
++}
++EXPORT_SYMBOL(__vcalloc);
++
++/**
++ * vcalloc - allocate and zero memory for a virtually contiguous array.
++ * @n: number of elements.
++ * @size: element size.
++ */
++void *vcalloc(size_t n, size_t size)
++{
++      return __vmalloc_array(n, size, GFP_KERNEL | __GFP_ZERO);
++}
++EXPORT_SYMBOL(vcalloc);
++
+ /* Neutral page->mapping pointer to address_space or anon_vma or other */
+ void *page_rmapping(struct page *page)
+ {
index 6ae4450a06d0830a8d250e6d77f901287700aafc..74ce7fa91f9c9edef1ca271ea6687cb657d447be 100644 (file)
@@ -36,4 +36,7 @@ nouveau-vmm-don-t-set-addr-on-the-fail-path-to-avoid-warning.patch
 ubifs-ubifs_symlink-fix-memleak-of-inode-i_link-in-error-path.patch
 rename-fix-the-locking-of-subdirectories.patch
 block-remove-special-casing-of-compound-pages.patch
-mm-page_alloc-unreserve-highatomic-page-blocks-before-oom.patch
+stddef-introduce-declare_flex_array-helper.patch
+smb3-replace-smb2pdu-1-element-arrays-with-flex-arrays.patch
+mm-vmalloc-introduce-array-allocation-functions.patch
+kvm-use-__vcalloc-for-very-large-allocations.patch
diff --git a/queue-5.10/smb3-replace-smb2pdu-1-element-arrays-with-flex-arrays.patch b/queue-5.10/smb3-replace-smb2pdu-1-element-arrays-with-flex-arrays.patch
new file mode 100644 (file)
index 0000000..b8610ff
--- /dev/null
@@ -0,0 +1,369 @@
+From stable+bounces-15922-greg=kroah.com@vger.kernel.org Fri Jan 26 11:33:27 2024
+From: kovalev@altlinux.org
+Date: Fri, 26 Jan 2024 22:31:43 +0300
+Subject: smb3: Replace smb2pdu 1-element arrays with flex-arrays
+To: stable@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org
+Cc: keescook@chromium.org, sfrench@samba.org, corbet@lwn.net, natechancellor@gmail.com, ndesaulniers@google.com, kovalev@altlinux.org, Paulo Alcantara <pc@cjr.nz>, Ronnie Sahlberg <lsahlber@redhat.com>, Shyam Prasad N <sprasad@microsoft.com>, Tom Talpey <tom@talpey.com>, Namjae Jeon <linkinjeon@kernel.org>, Sergey Senozhatsky <senozhatsky@chromium.org>, Steve French <stfrench@microsoft.com>
+Message-ID: <20240126193143.245122-3-kovalev@altlinux.org>
+
+From: Kees Cook <keescook@chromium.org>
+
+commit eb3e28c1e89b4984308777231887e41aa8a0151f upstream.
+
+The kernel is globally removing the ambiguous 0-length and 1-element
+arrays in favor of flexible arrays, so that we can gain both compile-time
+and run-time array bounds checking[1].
+
+Replace the trailing 1-element array with a flexible array in the
+following structures:
+
+        struct smb2_err_rsp
+        struct smb2_tree_connect_req
+        struct smb2_negotiate_rsp
+        struct smb2_sess_setup_req
+        struct smb2_sess_setup_rsp
+        struct smb2_read_req
+        struct smb2_read_rsp
+        struct smb2_write_req
+        struct smb2_write_rsp
+        struct smb2_query_directory_req
+        struct smb2_query_directory_rsp
+        struct smb2_set_info_req
+        struct smb2_change_notify_rsp
+        struct smb2_create_rsp
+        struct smb2_query_info_req
+        struct smb2_query_info_rsp
+
+Replace the trailing 1-element array with a flexible array, but leave
+the existing structure padding:
+
+        struct smb2_file_all_info
+        struct smb2_lock_req
+
+Adjust all related size calculations to match the changes to sizeof().
+
+No machine code output or .data section differences are produced after
+these changes.
+
+[1] For lots of details, see both:
+    https://docs.kernel.org/process/deprecated.html#zero-length-and-one-element-arrays
+    https://people.kernel.org/kees/bounded-flexible-arrays-in-c
+
+Cc: Steve French <sfrench@samba.org>
+Cc: Paulo Alcantara <pc@cjr.nz>
+Cc: Ronnie Sahlberg <lsahlber@redhat.com>
+Cc: Shyam Prasad N <sprasad@microsoft.com>
+Cc: Tom Talpey <tom@talpey.com>
+Cc: Namjae Jeon <linkinjeon@kernel.org>
+Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
+Cc: linux-cifs@vger.kernel.org
+Cc: samba-technical@lists.samba.org
+Reviewed-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Vasiliy Kovalev <kovalev@altlinux.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/cifs/smb2misc.c |    2 +-
+ fs/cifs/smb2ops.c  |   14 +++++++-------
+ fs/cifs/smb2pdu.c  |   13 ++++++-------
+ fs/cifs/smb2pdu.h  |   42 ++++++++++++++++++++++++------------------
+ 4 files changed, 38 insertions(+), 33 deletions(-)
+
+--- a/fs/cifs/smb2misc.c
++++ b/fs/cifs/smb2misc.c
+@@ -117,7 +117,7 @@ static __u32 get_neg_ctxt_len(struct smb
+       } else if (nc_offset + 1 == non_ctxlen) {
+               cifs_dbg(FYI, "no SPNEGO security blob in negprot rsp\n");
+               size_of_pad_before_neg_ctxts = 0;
+-      } else if (non_ctxlen == SMB311_NEGPROT_BASE_SIZE)
++      } else if (non_ctxlen == SMB311_NEGPROT_BASE_SIZE + 1)
+               /* has padding, but no SPNEGO blob */
+               size_of_pad_before_neg_ctxts = nc_offset - non_ctxlen + 1;
+       else
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -5561,7 +5561,7 @@ struct smb_version_values smb20_values =
+       .header_size = sizeof(struct smb2_sync_hdr),
+       .header_preamble_size = 0,
+       .max_header_size = MAX_SMB2_HDR_SIZE,
+-      .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
++      .read_rsp_size = sizeof(struct smb2_read_rsp),
+       .lock_cmd = SMB2_LOCK,
+       .cap_unix = 0,
+       .cap_nt_find = SMB2_NT_FIND,
+@@ -5583,7 +5583,7 @@ struct smb_version_values smb21_values =
+       .header_size = sizeof(struct smb2_sync_hdr),
+       .header_preamble_size = 0,
+       .max_header_size = MAX_SMB2_HDR_SIZE,
+-      .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
++      .read_rsp_size = sizeof(struct smb2_read_rsp),
+       .lock_cmd = SMB2_LOCK,
+       .cap_unix = 0,
+       .cap_nt_find = SMB2_NT_FIND,
+@@ -5604,7 +5604,7 @@ struct smb_version_values smb3any_values
+       .header_size = sizeof(struct smb2_sync_hdr),
+       .header_preamble_size = 0,
+       .max_header_size = MAX_SMB2_HDR_SIZE,
+-      .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
++      .read_rsp_size = sizeof(struct smb2_read_rsp),
+       .lock_cmd = SMB2_LOCK,
+       .cap_unix = 0,
+       .cap_nt_find = SMB2_NT_FIND,
+@@ -5625,7 +5625,7 @@ struct smb_version_values smbdefault_val
+       .header_size = sizeof(struct smb2_sync_hdr),
+       .header_preamble_size = 0,
+       .max_header_size = MAX_SMB2_HDR_SIZE,
+-      .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
++      .read_rsp_size = sizeof(struct smb2_read_rsp),
+       .lock_cmd = SMB2_LOCK,
+       .cap_unix = 0,
+       .cap_nt_find = SMB2_NT_FIND,
+@@ -5646,7 +5646,7 @@ struct smb_version_values smb30_values =
+       .header_size = sizeof(struct smb2_sync_hdr),
+       .header_preamble_size = 0,
+       .max_header_size = MAX_SMB2_HDR_SIZE,
+-      .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
++      .read_rsp_size = sizeof(struct smb2_read_rsp),
+       .lock_cmd = SMB2_LOCK,
+       .cap_unix = 0,
+       .cap_nt_find = SMB2_NT_FIND,
+@@ -5667,7 +5667,7 @@ struct smb_version_values smb302_values
+       .header_size = sizeof(struct smb2_sync_hdr),
+       .header_preamble_size = 0,
+       .max_header_size = MAX_SMB2_HDR_SIZE,
+-      .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
++      .read_rsp_size = sizeof(struct smb2_read_rsp),
+       .lock_cmd = SMB2_LOCK,
+       .cap_unix = 0,
+       .cap_nt_find = SMB2_NT_FIND,
+@@ -5688,7 +5688,7 @@ struct smb_version_values smb311_values
+       .header_size = sizeof(struct smb2_sync_hdr),
+       .header_preamble_size = 0,
+       .max_header_size = MAX_SMB2_HDR_SIZE,
+-      .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
++      .read_rsp_size = sizeof(struct smb2_read_rsp),
+       .lock_cmd = SMB2_LOCK,
+       .cap_unix = 0,
+       .cap_nt_find = SMB2_NT_FIND,
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -1261,7 +1261,7 @@ SMB2_sess_sendreceive(struct SMB2_sess_d
+       /* Testing shows that buffer offset must be at location of Buffer[0] */
+       req->SecurityBufferOffset =
+-              cpu_to_le16(sizeof(struct smb2_sess_setup_req) - 1 /* pad */);
++              cpu_to_le16(sizeof(struct smb2_sess_setup_req));
+       req->SecurityBufferLength = cpu_to_le16(sess_data->iov[1].iov_len);
+       memset(&rqst, 0, sizeof(struct smb_rqst));
+@@ -1760,8 +1760,7 @@ SMB2_tcon(const unsigned int xid, struct
+       iov[0].iov_len = total_len - 1;
+       /* Testing shows that buffer offset must be at location of Buffer[0] */
+-      req->PathOffset = cpu_to_le16(sizeof(struct smb2_tree_connect_req)
+-                      - 1 /* pad */);
++      req->PathOffset = cpu_to_le16(sizeof(struct smb2_tree_connect_req));
+       req->PathLength = cpu_to_le16(unc_path_len - 2);
+       iov[1].iov_base = unc_path;
+       iov[1].iov_len = unc_path_len;
+@@ -4676,7 +4675,7 @@ int SMB2_query_directory_init(const unsi
+       memcpy(bufptr, &asteriks, len);
+       req->FileNameOffset =
+-              cpu_to_le16(sizeof(struct smb2_query_directory_req) - 1);
++              cpu_to_le16(sizeof(struct smb2_query_directory_req));
+       req->FileNameLength = cpu_to_le16(len);
+       /*
+        * BB could be 30 bytes or so longer if we used SMB2 specific
+@@ -4873,7 +4872,7 @@ SMB2_set_info_init(struct cifs_tcon *tco
+       req->AdditionalInformation = cpu_to_le32(additional_info);
+       req->BufferOffset =
+-                      cpu_to_le16(sizeof(struct smb2_set_info_req) - 1);
++                      cpu_to_le16(sizeof(struct smb2_set_info_req));
+       req->BufferLength = cpu_to_le32(*size);
+       memcpy(req->Buffer, *data, *size);
+@@ -5105,9 +5104,9 @@ build_qfs_info_req(struct kvec *iov, str
+       req->VolatileFileId = volatile_fid;
+       /* 1 for pad */
+       req->InputBufferOffset =
+-                      cpu_to_le16(sizeof(struct smb2_query_info_req) - 1);
++                      cpu_to_le16(sizeof(struct smb2_query_info_req));
+       req->OutputBufferLength = cpu_to_le32(
+-              outbuf_len + sizeof(struct smb2_query_info_rsp) - 1);
++              outbuf_len + sizeof(struct smb2_query_info_rsp));
+       iov->iov_base = (char *)req;
+       iov->iov_len = total_len;
+--- a/fs/cifs/smb2pdu.h
++++ b/fs/cifs/smb2pdu.h
+@@ -220,7 +220,7 @@ struct smb2_err_rsp {
+       __le16 StructureSize;
+       __le16 Reserved; /* MBZ */
+       __le32 ByteCount;  /* even if zero, at least one byte follows */
+-      __u8   ErrorData[1];  /* variable length */
++      __u8   ErrorData[];  /* variable length */
+ } __packed;
+ #define SYMLINK_ERROR_TAG 0x4c4d5953
+@@ -464,7 +464,7 @@ struct smb2_negotiate_rsp {
+       __le16 SecurityBufferOffset;
+       __le16 SecurityBufferLength;
+       __le32 NegotiateContextOffset;  /* Pre:SMB3.1.1 was reserved/ignored */
+-      __u8   Buffer[1];       /* variable length GSS security buffer */
++      __u8   Buffer[];        /* variable length GSS security buffer */
+ } __packed;
+ /* Flags */
+@@ -481,7 +481,7 @@ struct smb2_sess_setup_req {
+       __le16 SecurityBufferOffset;
+       __le16 SecurityBufferLength;
+       __u64 PreviousSessionId;
+-      __u8   Buffer[1];       /* variable length GSS security buffer */
++      __u8   Buffer[];        /* variable length GSS security buffer */
+ } __packed;
+ /* Currently defined SessionFlags */
+@@ -494,7 +494,7 @@ struct smb2_sess_setup_rsp {
+       __le16 SessionFlags;
+       __le16 SecurityBufferOffset;
+       __le16 SecurityBufferLength;
+-      __u8   Buffer[1];       /* variable length GSS security buffer */
++      __u8   Buffer[];        /* variable length GSS security buffer */
+ } __packed;
+ struct smb2_logoff_req {
+@@ -520,7 +520,7 @@ struct smb2_tree_connect_req {
+       __le16 Flags; /* Reserved MBZ for dialects prior to SMB3.1.1 */
+       __le16 PathOffset;
+       __le16 PathLength;
+-      __u8   Buffer[1];       /* variable length */
++      __u8   Buffer[];        /* variable length */
+ } __packed;
+ /* See MS-SMB2 section 2.2.9.2 */
+@@ -828,7 +828,7 @@ struct smb2_create_rsp {
+       __u64  VolatileFileId; /* opaque endianness */
+       __le32 CreateContextsOffset;
+       __le32 CreateContextsLength;
+-      __u8   Buffer[1];
++      __u8   Buffer[];
+ } __packed;
+ struct create_context {
+@@ -1289,7 +1289,7 @@ struct smb2_read_plain_req {
+       __le32 RemainingBytes;
+       __le16 ReadChannelInfoOffset;
+       __le16 ReadChannelInfoLength;
+-      __u8   Buffer[1];
++      __u8   Buffer[];
+ } __packed;
+ /* Read flags */
+@@ -1304,7 +1304,7 @@ struct smb2_read_rsp {
+       __le32 DataLength;
+       __le32 DataRemaining;
+       __u32  Flags;
+-      __u8   Buffer[1];
++      __u8   Buffer[];
+ } __packed;
+ /* For write request Flags field below the following flags are defined: */
+@@ -1324,7 +1324,7 @@ struct smb2_write_req {
+       __le16 WriteChannelInfoOffset;
+       __le16 WriteChannelInfoLength;
+       __le32 Flags;
+-      __u8   Buffer[1];
++      __u8   Buffer[];
+ } __packed;
+ struct smb2_write_rsp {
+@@ -1335,7 +1335,7 @@ struct smb2_write_rsp {
+       __le32 DataLength;
+       __le32 DataRemaining;
+       __u32  Reserved2;
+-      __u8   Buffer[1];
++      __u8   Buffer[];
+ } __packed;
+ /* notify flags */
+@@ -1371,7 +1371,7 @@ struct smb2_change_notify_rsp {
+       __le16  StructureSize;  /* Must be 9 */
+       __le16  OutputBufferOffset;
+       __le32  OutputBufferLength;
+-      __u8    Buffer[1]; /* array of file notify structs */
++      __u8    Buffer[]; /* array of file notify structs */
+ } __packed;
+ #define SMB2_LOCKFLAG_SHARED_LOCK     0x0001
+@@ -1394,7 +1394,10 @@ struct smb2_lock_req {
+       __u64  PersistentFileId; /* opaque endianness */
+       __u64  VolatileFileId; /* opaque endianness */
+       /* Followed by at least one */
+-      struct smb2_lock_element locks[1];
++      union {
++              struct smb2_lock_element lock;
++              DECLARE_FLEX_ARRAY(struct smb2_lock_element, locks);
++      };
+ } __packed;
+ struct smb2_lock_rsp {
+@@ -1434,7 +1437,7 @@ struct smb2_query_directory_req {
+       __le16 FileNameOffset;
+       __le16 FileNameLength;
+       __le32 OutputBufferLength;
+-      __u8   Buffer[1];
++      __u8   Buffer[];
+ } __packed;
+ struct smb2_query_directory_rsp {
+@@ -1442,7 +1445,7 @@ struct smb2_query_directory_rsp {
+       __le16 StructureSize; /* Must be 9 */
+       __le16 OutputBufferOffset;
+       __le32 OutputBufferLength;
+-      __u8   Buffer[1];
++      __u8   Buffer[];
+ } __packed;
+ /* Possible InfoType values */
+@@ -1483,7 +1486,7 @@ struct smb2_query_info_req {
+       __le32 Flags;
+       __u64  PersistentFileId; /* opaque endianness */
+       __u64  VolatileFileId; /* opaque endianness */
+-      __u8   Buffer[1];
++      __u8   Buffer[];
+ } __packed;
+ struct smb2_query_info_rsp {
+@@ -1491,7 +1494,7 @@ struct smb2_query_info_rsp {
+       __le16 StructureSize; /* Must be 9 */
+       __le16 OutputBufferOffset;
+       __le32 OutputBufferLength;
+-      __u8   Buffer[1];
++      __u8   Buffer[];
+ } __packed;
+ /*
+@@ -1514,7 +1517,7 @@ struct smb2_set_info_req {
+       __le32 AdditionalInformation;
+       __u64  PersistentFileId; /* opaque endianness */
+       __u64  VolatileFileId; /* opaque endianness */
+-      __u8   Buffer[1];
++      __u8   Buffer[];
+ } __packed;
+ struct smb2_set_info_rsp {
+@@ -1716,7 +1719,10 @@ struct smb2_file_all_info { /* data bloc
+       __le32 Mode;
+       __le32 AlignmentRequirement;
+       __le32 FileNameLength;
+-      char   FileName[1];
++      union {
++              char __pad;     /* Legacy structure padding */
++              DECLARE_FLEX_ARRAY(char, FileName);
++      };
+ } __packed; /* level 18 Query */
+ struct smb2_file_eof_info { /* encoding of request for level 10 */
diff --git a/queue-5.10/stddef-introduce-declare_flex_array-helper.patch b/queue-5.10/stddef-introduce-declare_flex_array-helper.patch
new file mode 100644 (file)
index 0000000..492e0af
--- /dev/null
@@ -0,0 +1,152 @@
+From stable+bounces-15920-greg=kroah.com@vger.kernel.org Fri Jan 26 11:32:58 2024
+From: kovalev@altlinux.org
+Date: Fri, 26 Jan 2024 22:31:42 +0300
+Subject: stddef: Introduce DECLARE_FLEX_ARRAY() helper
+To: stable@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org
+Cc: keescook@chromium.org, sfrench@samba.org, corbet@lwn.net, natechancellor@gmail.com, ndesaulniers@google.com, kovalev@altlinux.org, Arnd Bergmann <arnd@arndb.de>, "Gustavo A. R. Silva" <gustavoars@kernel.org>
+Message-ID: <20240126193143.245122-2-kovalev@altlinux.org>
+
+From: Kees Cook <keescook@chromium.org>
+
+commit 3080ea5553cc909b000d1f1d964a9041962f2c5b upstream.
+
+There are many places where kernel code wants to have several different
+typed trailing flexible arrays. This would normally be done with multiple
+flexible arrays in a union, but since GCC and Clang don't (on the surface)
+allow this, there have been many open-coded workarounds, usually involving
+neighboring 0-element arrays at the end of a structure. For example,
+instead of something like this:
+
+struct thing {
+       ...
+       union {
+               struct type1 foo[];
+               struct type2 bar[];
+       };
+};
+
+code works around the compiler with:
+
+struct thing {
+       ...
+       struct type1 foo[0];
+       struct type2 bar[];
+};
+
+Another case is when a flexible array is wanted as the single member
+within a struct (which itself is usually in a union). For example, this
+would be worked around as:
+
+union many {
+       ...
+       struct {
+               struct type3 baz[0];
+       };
+};
+
+These kinds of work-arounds cause problems with size checks against such
+zero-element arrays (for example when building with -Warray-bounds and
+-Wzero-length-bounds, and with the coming FORTIFY_SOURCE improvements),
+so they must all be converted to "real" flexible arrays, avoiding warnings
+like this:
+
+fs/hpfs/anode.c: In function 'hpfs_add_sector_to_btree':
+fs/hpfs/anode.c:209:27: warning: array subscript 0 is outside the bounds of an interior zero-length array 'struct bplus_internal_node[0]' [-Wzero-length-bounds]
+  209 |    anode->btree.u.internal[0].down = cpu_to_le32(a);
+      |    ~~~~~~~~~~~~~~~~~~~~~~~^~~
+In file included from fs/hpfs/hpfs_fn.h:26,
+                 from fs/hpfs/anode.c:10:
+fs/hpfs/hpfs.h:412:32: note: while referencing 'internal'
+  412 |     struct bplus_internal_node internal[0]; /* (internal) 2-word entries giving
+      |                                ^~~~~~~~
+
+drivers/net/can/usb/etas_es58x/es58x_fd.c: In function 'es58x_fd_tx_can_msg':
+drivers/net/can/usb/etas_es58x/es58x_fd.c:360:35: warning: array subscript 65535 is outside the bounds of an interior zero-length array 'u8[0]' {aka 'unsigned char[]'} [-Wzero-length-bounds]
+  360 |  tx_can_msg = (typeof(tx_can_msg))&es58x_fd_urb_cmd->raw_msg[msg_len];
+      |                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In file included from drivers/net/can/usb/etas_es58x/es58x_core.h:22,
+                 from drivers/net/can/usb/etas_es58x/es58x_fd.c:17:
+drivers/net/can/usb/etas_es58x/es58x_fd.h:231:6: note: while referencing 'raw_msg'
+  231 |   u8 raw_msg[0];
+      |      ^~~~~~~
+
+However, it _is_ entirely possible to have one or more flexible arrays
+in a struct or union: it just has to be in another struct. And since it
+cannot be alone in a struct, such a struct must have at least 1 other
+named member -- but that member can be zero sized. Wrap all this nonsense
+into the new DECLARE_FLEX_ARRAY() in support of having flexible arrays
+in unions (or alone in a struct).
+
+As with struct_group(), since this is needed in UAPI headers as well,
+implement the core there, with a non-UAPI wrapper.
+
+Additionally update kernel-doc to understand its existence.
+
+https://github.com/KSPP/linux/issues/137
+
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: "Gustavo A. R. Silva" <gustavoars@kernel.org>
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Vasiliy Kovalev <kovalev@altlinux.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/stddef.h      |   13 +++++++++++++
+ include/uapi/linux/stddef.h |   16 ++++++++++++++++
+ scripts/kernel-doc          |    3 ++-
+ 3 files changed, 31 insertions(+), 1 deletion(-)
+
+--- a/include/linux/stddef.h
++++ b/include/linux/stddef.h
+@@ -84,4 +84,17 @@ enum {
+ #define struct_group_tagged(TAG, NAME, MEMBERS...) \
+       __struct_group(TAG, NAME, /* no attrs */, MEMBERS)
++/**
++ * DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union
++ *
++ * @TYPE: The type of each flexible array element
++ * @NAME: The name of the flexible array member
++ *
++ * In order to have a flexible array member in a union or alone in a
++ * struct, it needs to be wrapped in an anonymous struct with at least 1
++ * named member, but that member can be empty.
++ */
++#define DECLARE_FLEX_ARRAY(TYPE, NAME) \
++      __DECLARE_FLEX_ARRAY(TYPE, NAME)
++
+ #endif
+--- a/include/uapi/linux/stddef.h
++++ b/include/uapi/linux/stddef.h
+@@ -28,4 +28,20 @@
+               struct { MEMBERS } ATTRS; \
+               struct TAG { MEMBERS } ATTRS NAME; \
+       }
++
++/**
++ * __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union
++ *
++ * @TYPE: The type of each flexible array element
++ * @NAME: The name of the flexible array member
++ *
++ * In order to have a flexible array member in a union or alone in a
++ * struct, it needs to be wrapped in an anonymous struct with at least 1
++ * named member, but that member can be empty.
++ */
++#define __DECLARE_FLEX_ARRAY(TYPE, NAME)      \
++      struct { \
++              struct { } __empty_ ## NAME; \
++              TYPE NAME[]; \
++      }
+ #endif
+--- a/scripts/kernel-doc
++++ b/scripts/kernel-doc
+@@ -1232,7 +1232,8 @@ sub dump_struct($$) {
+       $members =~ s/DECLARE_KFIFO\s*\(([^,)]+),\s*([^,)]+),\s*([^,)]+)\)/$2 \*$1/gos;
+       # replace DECLARE_KFIFO_PTR
+       $members =~ s/DECLARE_KFIFO_PTR\s*\(([^,)]+),\s*([^,)]+)\)/$2 \*$1/gos;
+-
++      # replace DECLARE_FLEX_ARRAY
++      $members =~ s/(?:__)?DECLARE_FLEX_ARRAY\s*\($args,\s*$args\)/$1 $2\[\]/gos;
+       my $declaration = $members;
+       # Split nested struct/union elements as newer ones