]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Jun 2026 11:36:36 +0000 (12:36 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Jun 2026 11:36:36 +0000 (12:36 +0100)
added patches:
arm64-scripts-sorttable-implement-sorting-mcount_loc-at-boot-for-arm64.patch
ftrace-check-against-is_kernel_text-instead-of-kaslr_offset.patch
ftrace-do-not-over-allocate-ftrace-memory.patch
ftrace-have-ftrace-pages-output-reflect-freed-pages.patch
ftrace-test-mcount_loc-addr-before-calling-ftrace_call_addr.patch
ftrace-update-the-mcount_loc-check-of-skipped-entries.patch
net-ipv6-make-udp_tunnel6_xmit_skb-void.patch
scripts-sorttable-add-helper-functions-for-elf_ehdr.patch
scripts-sorttable-add-helper-functions-for-elf_shdr.patch
scripts-sorttable-add-helper-functions-for-elf_sym.patch
scripts-sorttable-allow-matches-to-functions-before-function-entry.patch
scripts-sorttable-always-use-an-array-for-the-mcount_loc-sorting.patch
scripts-sorttable-convert-elf_ehdr-to-union.patch
scripts-sorttable-convert-elf_sym-macro-over-to-a-union.patch
scripts-sorttable-fix-endianness-handling-in-build-time-mcount-sort.patch
scripts-sorttable-get-start-stop_mcount_loc-from-elf-file-directly.patch
scripts-sorttable-have-mcount-rela-sort-use-direct-values.patch
scripts-sorttable-have-the-orc-code-use-the-_r-functions-to-read.patch
scripts-sorttable-make-compare_extable-into-two-functions.patch
scripts-sorttable-move-code-from-sorttable.h-into-sorttable.c.patch
scripts-sorttable-remove-unneeded-elf_rel.patch
scripts-sorttable-remove-unused-macro-defines.patch
scripts-sorttable-remove-unused-write-functions.patch
scripts-sorttable-replace-elf_shdr-macro-with-a-union.patch
scripts-sorttable-use-a-structure-of-function-pointers-for-elf-helpers.patch
scripts-sorttable-use-normal-sort-if-theres-no-relocs-in-the-mcount-section.patch
scripts-sorttable-use-uint64_t-for-mcount-sorting.patch
scripts-sorttable-zero-out-weak-functions-in-mcount_loc-table.patch
sctp-disable-bh-before-calling-udp_tunnel_xmit_skb.patch

30 files changed:
queue-6.12/arm64-scripts-sorttable-implement-sorting-mcount_loc-at-boot-for-arm64.patch [new file with mode: 0644]
queue-6.12/ftrace-check-against-is_kernel_text-instead-of-kaslr_offset.patch [new file with mode: 0644]
queue-6.12/ftrace-do-not-over-allocate-ftrace-memory.patch [new file with mode: 0644]
queue-6.12/ftrace-have-ftrace-pages-output-reflect-freed-pages.patch [new file with mode: 0644]
queue-6.12/ftrace-test-mcount_loc-addr-before-calling-ftrace_call_addr.patch [new file with mode: 0644]
queue-6.12/ftrace-update-the-mcount_loc-check-of-skipped-entries.patch [new file with mode: 0644]
queue-6.12/net-ipv6-make-udp_tunnel6_xmit_skb-void.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-add-helper-functions-for-elf_ehdr.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-add-helper-functions-for-elf_shdr.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-add-helper-functions-for-elf_sym.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-allow-matches-to-functions-before-function-entry.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-always-use-an-array-for-the-mcount_loc-sorting.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-convert-elf_ehdr-to-union.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-convert-elf_sym-macro-over-to-a-union.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-fix-endianness-handling-in-build-time-mcount-sort.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-get-start-stop_mcount_loc-from-elf-file-directly.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-have-mcount-rela-sort-use-direct-values.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-have-the-orc-code-use-the-_r-functions-to-read.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-make-compare_extable-into-two-functions.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-move-code-from-sorttable.h-into-sorttable.c.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-remove-unneeded-elf_rel.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-remove-unused-macro-defines.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-remove-unused-write-functions.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-replace-elf_shdr-macro-with-a-union.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-use-a-structure-of-function-pointers-for-elf-helpers.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-use-normal-sort-if-theres-no-relocs-in-the-mcount-section.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-use-uint64_t-for-mcount-sorting.patch [new file with mode: 0644]
queue-6.12/scripts-sorttable-zero-out-weak-functions-in-mcount_loc-table.patch [new file with mode: 0644]
queue-6.12/sctp-disable-bh-before-calling-udp_tunnel_xmit_skb.patch [new file with mode: 0644]
queue-6.12/series

diff --git a/queue-6.12/arm64-scripts-sorttable-implement-sorting-mcount_loc-at-boot-for-arm64.patch b/queue-6.12/arm64-scripts-sorttable-implement-sorting-mcount_loc-at-boot-for-arm64.patch
new file mode 100644 (file)
index 0000000..6994d4b
--- /dev/null
@@ -0,0 +1,363 @@
+From stable+bounces-267216-greg=kroah.com@vger.kernel.org Thu Jun 18 21:16:18 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:30 -0400
+Subject: arm64: scripts/sorttable: Implement sorting mcount_loc at boot for arm64
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <bf4bcdb583a211d91e2e566510551b8dab733ea5.1781809956.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit b3d09d06e052e1d754645acea4e4d1e96f81c934 ]
+
+The mcount_loc section holds the addresses of the functions that get
+patched by ftrace when enabling function callbacks. It can contain tens of
+thousands of entries. These addresses must be sorted. If they are not
+sorted at compile time, they are sorted at boot. Sorting at boot does take
+some time and does have a small impact on boot performance.
+
+x86 and arm32 have the addresses in the mcount_loc section of the ELF
+file. But for arm64, the section just contains zeros. The .rela.dyn
+Elf_Rela section holds the addresses and they get patched at boot during
+the relocation phase.
+
+In order to sort these addresses, the Elf_Rela needs to be updated instead
+of the location in the binary that holds the mcount_loc section. Have the
+sorttable code, allocate an array to hold the functions, load the
+addresses from the Elf_Rela entries, sort them, then put them back in
+order into the Elf_rela entries so that they will be sorted at boot up
+without having to sort them during boot up.
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Heiko Carstens <hca@linux.ibm.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: Vasily Gorbik <gor@linux.ibm.com>
+Cc: Alexander Gordeev <agordeev@linux.ibm.com>
+Link: https://lore.kernel.org/20250218200022.373319428@goodmis.org
+Acked-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/Kconfig  |    1 
+ scripts/sorttable.c |  185 +++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 183 insertions(+), 3 deletions(-)
+
+--- a/arch/arm64/Kconfig
++++ b/arch/arm64/Kconfig
+@@ -212,6 +212,7 @@ config ARM64
+               if DYNAMIC_FTRACE_WITH_ARGS
+       select HAVE_SAMPLE_FTRACE_DIRECT
+       select HAVE_SAMPLE_FTRACE_DIRECT_MULTI
++      select HAVE_BUILDTIME_MCOUNT_SORT
+       select HAVE_EFFICIENT_UNALIGNED_ACCESS
+       select HAVE_GUP_FAST
+       select HAVE_FTRACE_MCOUNT_RECORD
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -28,6 +28,7 @@
+ #include <fcntl.h>
+ #include <stdio.h>
+ #include <stdlib.h>
++#include <stdbool.h>
+ #include <string.h>
+ #include <unistd.h>
+ #include <errno.h>
+@@ -79,10 +80,16 @@ typedef union {
+       Elf64_Sym       e64;
+ } Elf_Sym;
++typedef union {
++      Elf32_Rela      e32;
++      Elf64_Rela      e64;
++} Elf_Rela;
++
+ static uint32_t (*r)(const uint32_t *);
+ static uint16_t (*r2)(const uint16_t *);
+ static uint64_t (*r8)(const uint64_t *);
+ static void (*w)(uint32_t, uint32_t *);
++static void (*w8)(uint64_t, uint64_t *);
+ typedef void (*table_sort_t)(char *, int);
+ static struct elf_funcs {
+@@ -102,6 +109,10 @@ static struct elf_funcs {
+       uint32_t (*sym_name)(Elf_Sym *sym);
+       uint64_t (*sym_value)(Elf_Sym *sym);
+       uint16_t (*sym_shndx)(Elf_Sym *sym);
++      uint64_t (*rela_offset)(Elf_Rela *rela);
++      uint64_t (*rela_info)(Elf_Rela *rela);
++      uint64_t (*rela_addend)(Elf_Rela *rela);
++      void (*rela_write_addend)(Elf_Rela *rela, uint64_t val);
+ } e;
+ static uint64_t ehdr64_shoff(Elf_Ehdr *ehdr)
+@@ -262,6 +273,38 @@ SYM_ADDR(value)
+ SYM_WORD(name)
+ SYM_HALF(shndx)
++#define __maybe_unused                        __attribute__((__unused__))
++
++#define RELA_ADDR(fn_name)                                    \
++static uint64_t rela64_##fn_name(Elf_Rela *rela)              \
++{                                                             \
++      return r8((uint64_t *)&rela->e64.r_##fn_name);          \
++}                                                             \
++                                                              \
++static uint64_t rela32_##fn_name(Elf_Rela *rela)              \
++{                                                             \
++      return r((uint32_t *)&rela->e32.r_##fn_name);           \
++}                                                             \
++                                                              \
++static uint64_t __maybe_unused rela_##fn_name(Elf_Rela *rela) \
++{                                                             \
++      return e.rela_##fn_name(rela);                          \
++}
++
++RELA_ADDR(offset)
++RELA_ADDR(info)
++RELA_ADDR(addend)
++
++static void rela64_write_addend(Elf_Rela *rela, uint64_t val)
++{
++      w8(val, (uint64_t *)&rela->e64.r_addend);
++}
++
++static void rela32_write_addend(Elf_Rela *rela, uint64_t val)
++{
++      w(val, (uint32_t *)&rela->e32.r_addend);
++}
++
+ /*
+  * Get the whole file as a programming convenience in order to avoid
+  * malloc+lseek+read+free of many pieces.  If successful, then mmap
+@@ -341,6 +384,16 @@ static void wle(uint32_t val, uint32_t *
+       put_unaligned_le32(val, x);
+ }
++static void w8be(uint64_t val, uint64_t *x)
++{
++      put_unaligned_be64(val, x);
++}
++
++static void w8le(uint64_t val, uint64_t *x)
++{
++      put_unaligned_le64(val, x);
++}
++
+ /*
+  * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of
+  * the way to -256..-1, to avoid conflicting with real section
+@@ -398,13 +451,12 @@ static inline void *get_index(void *star
+ static int extable_ent_size;
+ static int long_size;
++#define ERRSTR_MAXSZ  256
+ #ifdef UNWINDER_ORC_ENABLED
+ /* ORC unwinder only support X86_64 */
+ #include <asm/orc_types.h>
+-#define ERRSTR_MAXSZ  256
+-
+ static char g_err[ERRSTR_MAXSZ];
+ static int *g_orc_ip_table;
+ static struct orc_entry *g_orc_table;
+@@ -499,7 +551,19 @@ static void *sort_orctable(void *arg)
+ #endif
+ #ifdef MCOUNT_SORT_ENABLED
++
++/* Only used for sorting mcount table */
++static void rela_write_addend(Elf_Rela *rela, uint64_t val)
++{
++      e.rela_write_addend(rela, val);
++}
++
+ static pthread_t mcount_sort_thread;
++static bool sort_reloc;
++
++static long rela_type;
++
++static char m_err[ERRSTR_MAXSZ];
+ struct elf_mcount_loc {
+       Elf_Ehdr *ehdr;
+@@ -508,6 +572,103 @@ struct elf_mcount_loc {
+       uint64_t stop_mcount_loc;
+ };
++/* Sort the relocations not the address itself */
++static void *sort_relocs(Elf_Ehdr *ehdr, uint64_t start_loc, uint64_t size)
++{
++      Elf_Shdr *shdr_start;
++      Elf_Rela *rel;
++      unsigned int shnum;
++      unsigned int count;
++      int shentsize;
++      void *vals;
++      void *ptr;
++
++      shdr_start = (Elf_Shdr *)((char *)ehdr + ehdr_shoff(ehdr));
++      shentsize = ehdr_shentsize(ehdr);
++
++      vals = malloc(long_size * size);
++      if (!vals) {
++              snprintf(m_err, ERRSTR_MAXSZ, "Failed to allocate sort array");
++              pthread_exit(m_err);
++              return NULL;
++      }
++
++      ptr = vals;
++
++      shnum = ehdr_shnum(ehdr);
++      if (shnum == SHN_UNDEF)
++              shnum = shdr_size(shdr_start);
++
++      for (int i = 0; i < shnum; i++) {
++              Elf_Shdr *shdr = get_index(shdr_start, shentsize, i);
++              void *end;
++
++              if (shdr_type(shdr) != SHT_RELA)
++                      continue;
++
++              rel = (void *)ehdr + shdr_offset(shdr);
++              end = (void *)rel + shdr_size(shdr);
++
++              for (; (void *)rel < end; rel = (void *)rel + shdr_entsize(shdr)) {
++                      uint64_t offset = rela_offset(rel);
++
++                      if (offset >= start_loc && offset < start_loc + size) {
++                              if (ptr + long_size > vals + size) {
++                                      free(vals);
++                                      snprintf(m_err, ERRSTR_MAXSZ,
++                                               "Too many relocations");
++                                      pthread_exit(m_err);
++                                      return NULL;
++                              }
++
++                              /* Make sure this has the correct type */
++                              if (rela_info(rel) != rela_type) {
++                                      free(vals);
++                                      snprintf(m_err, ERRSTR_MAXSZ,
++                                              "rela has type %lx but expected %lx\n",
++                                              (long)rela_info(rel), rela_type);
++                                      pthread_exit(m_err);
++                                      return NULL;
++                              }
++
++                              if (long_size == 4)
++                                      *(uint32_t *)ptr = rela_addend(rel);
++                              else
++                                      *(uint64_t *)ptr = rela_addend(rel);
++                              ptr += long_size;
++                      }
++              }
++      }
++      count = ptr - vals;
++      qsort(vals, count / long_size, long_size, compare_extable);
++
++      ptr = vals;
++      for (int i = 0; i < shnum; i++) {
++              Elf_Shdr *shdr = get_index(shdr_start, shentsize, i);
++              void *end;
++
++              if (shdr_type(shdr) != SHT_RELA)
++                      continue;
++
++              rel = (void *)ehdr + shdr_offset(shdr);
++              end = (void *)rel + shdr_size(shdr);
++
++              for (; (void *)rel < end; rel = (void *)rel + shdr_entsize(shdr)) {
++                      uint64_t offset = rela_offset(rel);
++
++                      if (offset >= start_loc && offset < start_loc + size) {
++                              if (long_size == 4)
++                                      rela_write_addend(rel, *(uint32_t *)ptr);
++                              else
++                                      rela_write_addend(rel, *(uint64_t *)ptr);
++                              ptr += long_size;
++                      }
++              }
++      }
++      free(vals);
++      return NULL;
++}
++
+ /* Sort the addresses stored between __start_mcount_loc to __stop_mcount_loc in vmlinux */
+ static void *sort_mcount_loc(void *arg)
+ {
+@@ -517,6 +678,9 @@ static void *sort_mcount_loc(void *arg)
+       uint64_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc;
+       unsigned char *start_loc = (void *)emloc->ehdr + offset;
++      if (sort_reloc)
++              return sort_relocs(emloc->ehdr, emloc->start_mcount_loc, count);
++
+       qsort(start_loc, count/long_size, long_size, compare_extable);
+       return NULL;
+ }
+@@ -866,12 +1030,14 @@ static int do_file(char const *const fna
+               r2      = r2le;
+               r8      = r8le;
+               w       = wle;
++              w8      = w8le;
+               break;
+       case ELFDATA2MSB:
+               r       = rbe;
+               r2      = r2be;
+               r8      = r8be;
+               w       = wbe;
++              w8      = w8be;
+               break;
+       default:
+               fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
+@@ -887,8 +1053,13 @@ static int do_file(char const *const fna
+       }
+       switch (r2(&ehdr->e32.e_machine)) {
+-      case EM_386:
+       case EM_AARCH64:
++#ifdef MCOUNT_SORT_ENABLED
++              sort_reloc = true;
++              rela_type = 0x403;
++#endif
++              /* fallthrough */
++      case EM_386:
+       case EM_LOONGARCH:
+       case EM_RISCV:
+       case EM_S390:
+@@ -932,6 +1103,10 @@ static int do_file(char const *const fna
+                       .sym_name               = sym32_name,
+                       .sym_value              = sym32_value,
+                       .sym_shndx              = sym32_shndx,
++                      .rela_offset            = rela32_offset,
++                      .rela_info              = rela32_info,
++                      .rela_addend            = rela32_addend,
++                      .rela_write_addend      = rela32_write_addend,
+               };
+               e = efuncs;
+@@ -965,6 +1140,10 @@ static int do_file(char const *const fna
+                       .sym_name               = sym64_name,
+                       .sym_value              = sym64_value,
+                       .sym_shndx              = sym64_shndx,
++                      .rela_offset            = rela64_offset,
++                      .rela_info              = rela64_info,
++                      .rela_addend            = rela64_addend,
++                      .rela_write_addend      = rela64_write_addend,
+               };
+               e = efuncs;
diff --git a/queue-6.12/ftrace-check-against-is_kernel_text-instead-of-kaslr_offset.patch b/queue-6.12/ftrace-check-against-is_kernel_text-instead-of-kaslr_offset.patch
new file mode 100644 (file)
index 0000000..88849b5
--- /dev/null
@@ -0,0 +1,81 @@
+From stable+bounces-267224-greg=kroah.com@vger.kernel.org Thu Jun 18 21:16:33 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:38 -0400
+Subject: ftrace: Check against is_kernel_text() instead of kaslr_offset()
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <0fb5f2bc351b85c4658cb247b9dc2f79b927d5ad.1781809982.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit da0f622b344be769ed61e7c1caf95cd0cdb47964 ]
+
+As kaslr_offset() is architecture dependent and also may not be defined by
+all architectures, when zeroing out unused weak functions, do not check
+against kaslr_offset(), but instead check if the address is within the
+kernel text sections. If KASLR added a shift to the zeroed out function,
+it would still not be located in the kernel text. This is a more robust
+way to test if the text is valid or not.
+
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: "Arnd Bergmann" <arnd@arndb.de>
+Link: https://lore.kernel.org/20250225182054.471759017@goodmis.org
+Fixes: ef378c3b8233 ("scripts/sorttable: Zero out weak functions in mcount_loc table")
+Reported-by: Nathan Chancellor <nathan@kernel.org>
+Reported-by: Mark Brown <broonie@kernel.org>
+Tested-by: Nathan Chancellor <nathan@kernel.org>
+Closes: https://lore.kernel.org/all/20250224180805.GA1536711@ax162/
+Closes: https://lore.kernel.org/all/5225b07b-a9b2-4558-9d5f-aa60b19f6317@sirena.org.uk/
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/ftrace.c |   17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+--- a/kernel/trace/ftrace.c
++++ b/kernel/trace/ftrace.c
+@@ -7051,7 +7051,6 @@ static int ftrace_process_locs(struct mo
+       unsigned long count;
+       unsigned long *p;
+       unsigned long addr;
+-      unsigned long kaslr;
+       unsigned long flags = 0; /* Shut up gcc */
+       unsigned long pages;
+       int ret = -ENOMEM;
+@@ -7101,9 +7100,6 @@ static int ftrace_process_locs(struct mo
+               ftrace_pages->next = start_pg;
+       }
+-      /* For zeroed locations that were shifted for core kernel */
+-      kaslr = !mod ? kaslr_offset() : 0;
+-
+       p = start;
+       pg = start_pg;
+       while (p < end) {
+@@ -7117,7 +7113,18 @@ static int ftrace_process_locs(struct mo
+                * object files to satisfy alignments.
+                * Skip any NULL pointers.
+                */
+-              if (!addr || addr == kaslr) {
++              if (!addr) {
++                      skipped++;
++                      continue;
++              }
++
++              /*
++               * If this is core kernel, make sure the address is in core
++               * or inittext, as weak functions get zeroed and KASLR can
++               * move them to something other than zero. It just will not
++               * move it to an area where kernel text is.
++               */
++              if (!mod && !(is_kernel_text(addr) || is_kernel_inittext(addr))) {
+                       skipped++;
+                       continue;
+               }
diff --git a/queue-6.12/ftrace-do-not-over-allocate-ftrace-memory.patch b/queue-6.12/ftrace-do-not-over-allocate-ftrace-memory.patch
new file mode 100644 (file)
index 0000000..3b75656
--- /dev/null
@@ -0,0 +1,163 @@
+From stable+bounces-267222-greg=kroah.com@vger.kernel.org Thu Jun 18 21:16:31 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:36 -0400
+Subject: ftrace: Do not over-allocate ftrace memory
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <5b5d88723e570c56841c83c78147d9badd595e1d.1781809976.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit be55257fab181b93af38f8c4b1b3cb453a78d742 ]
+
+The pg_remaining calculation in ftrace_process_locs() assumes that
+ENTRIES_PER_PAGE multiplied by 2^order equals the actual capacity of the
+allocated page group. However, ENTRIES_PER_PAGE is PAGE_SIZE / ENTRY_SIZE
+(integer division). When PAGE_SIZE is not a multiple of ENTRY_SIZE (e.g.
+4096 / 24 = 170 with remainder 16), high-order allocations (like 256 pages)
+have significantly more capacity than 256 * 170. This leads to pg_remaining
+being underestimated, which in turn makes skip (derived from skipped -
+pg_remaining) larger than expected, causing the WARN(skip != remaining)
+to trigger.
+
+Extra allocated pages for ftrace: 2 with 654 skipped
+WARNING: CPU: 0 PID: 0 at kernel/trace/ftrace.c:7295 ftrace_process_locs+0x5bf/0x5e0
+
+A similar problem in ftrace_allocate_records() can result in allocating
+too many pages. This can trigger the second warning in
+ftrace_process_locs().
+
+Extra allocated pages for ftrace
+WARNING: CPU: 0 PID: 0 at kernel/trace/ftrace.c:7276 ftrace_process_locs+0x548/0x580
+
+Use the actual capacity of a page group to determine the number of pages
+to allocate. Have ftrace_allocate_pages() return the number of allocated
+pages to avoid having to calculate it. Use the actual page group capacity
+when validating the number of unused pages due to skipped entries.
+Drop the definition of ENTRIES_PER_PAGE since it is no longer used.
+
+Cc: stable@vger.kernel.org
+Fixes: 4a3efc6baff93 ("ftrace: Update the mcount_loc check of skipped entries")
+Link: https://patch.msgid.link/20260113152243.3557219-1-linux@roeck-us.net
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/ftrace.c |   29 +++++++++++++++--------------
+ 1 file changed, 15 insertions(+), 14 deletions(-)
+
+--- a/kernel/trace/ftrace.c
++++ b/kernel/trace/ftrace.c
+@@ -1122,7 +1122,6 @@ struct ftrace_page {
+ };
+ #define ENTRY_SIZE sizeof(struct dyn_ftrace)
+-#define ENTRIES_PER_PAGE (PAGE_SIZE / ENTRY_SIZE)
+ static struct ftrace_page     *ftrace_pages_start;
+ static struct ftrace_page     *ftrace_pages;
+@@ -3754,7 +3753,8 @@ static int ftrace_update_code(struct mod
+       return 0;
+ }
+-static int ftrace_allocate_records(struct ftrace_page *pg, int count)
++static int ftrace_allocate_records(struct ftrace_page *pg, int count,
++                                 unsigned long *num_pages)
+ {
+       int order;
+       int pages;
+@@ -3764,7 +3764,7 @@ static int ftrace_allocate_records(struc
+               return -EINVAL;
+       /* We want to fill as much as possible, with no empty pages */
+-      pages = DIV_ROUND_UP(count, ENTRIES_PER_PAGE);
++      pages = DIV_ROUND_UP(count * ENTRY_SIZE, PAGE_SIZE);
+       order = fls(pages) - 1;
+  again:
+@@ -3779,6 +3779,7 @@ static int ftrace_allocate_records(struc
+       }
+       ftrace_number_of_pages += 1 << order;
++      *num_pages += 1 << order;
+       ftrace_number_of_groups++;
+       cnt = (PAGE_SIZE << order) / ENTRY_SIZE;
+@@ -3807,12 +3808,14 @@ static void ftrace_free_pages(struct ftr
+ }
+ static struct ftrace_page *
+-ftrace_allocate_pages(unsigned long num_to_init)
++ftrace_allocate_pages(unsigned long num_to_init, unsigned long *num_pages)
+ {
+       struct ftrace_page *start_pg;
+       struct ftrace_page *pg;
+       int cnt;
++      *num_pages = 0;
++
+       if (!num_to_init)
+               return NULL;
+@@ -3826,7 +3829,7 @@ ftrace_allocate_pages(unsigned long num_
+        * waste as little space as possible.
+        */
+       for (;;) {
+-              cnt = ftrace_allocate_records(pg, num_to_init);
++              cnt = ftrace_allocate_records(pg, num_to_init, num_pages);
+               if (cnt < 0)
+                       goto free_pages;
+@@ -7058,8 +7061,6 @@ static int ftrace_process_locs(struct mo
+       if (!count)
+               return 0;
+-      pages = DIV_ROUND_UP(count, ENTRIES_PER_PAGE);
+-
+       /*
+        * Sorting mcount in vmlinux at build time depend on
+        * CONFIG_BUILDTIME_MCOUNT_SORT, while mcount loc in
+@@ -7072,7 +7073,7 @@ static int ftrace_process_locs(struct mo
+               test_is_sorted(start, count);
+       }
+-      start_pg = ftrace_allocate_pages(count);
++      start_pg = ftrace_allocate_pages(count, &pages);
+       if (!start_pg)
+               return -ENOMEM;
+@@ -7159,27 +7160,27 @@ static int ftrace_process_locs(struct mo
+       /* We should have used all pages unless we skipped some */
+       if (pg_unuse) {
+               unsigned long pg_remaining, remaining = 0;
+-              unsigned long skip;
++              long skip;
+               /* Count the number of entries unused and compare it to skipped. */
+-              pg_remaining = (ENTRIES_PER_PAGE << pg->order) - pg->index;
++              pg_remaining = (PAGE_SIZE << pg->order) / ENTRY_SIZE - pg->index;
+               if (!WARN(skipped < pg_remaining, "Extra allocated pages for ftrace")) {
+                       skip = skipped - pg_remaining;
+-                      for (pg = pg_unuse; pg; pg = pg->next)
++                      for (pg = pg_unuse; pg && skip > 0; pg = pg->next) {
+                               remaining += 1 << pg->order;
++                              skip -= (PAGE_SIZE << pg->order) / ENTRY_SIZE;
++                      }
+                       pages -= remaining;
+-                      skip = DIV_ROUND_UP(skip, ENTRIES_PER_PAGE);
+-
+                       /*
+                        * Check to see if the number of pages remaining would
+                        * just fit the number of entries skipped.
+                        */
+-                      WARN(skip != remaining, "Extra allocated pages for ftrace: %lu with %lu skipped",
++                      WARN(pg || skip > 0, "Extra allocated pages for ftrace: %lu with %lu skipped",
+                            remaining, skipped);
+               }
+               /* Need to synchronize with ftrace_location_range() */
diff --git a/queue-6.12/ftrace-have-ftrace-pages-output-reflect-freed-pages.patch b/queue-6.12/ftrace-have-ftrace-pages-output-reflect-freed-pages.patch
new file mode 100644 (file)
index 0000000..c2396e9
--- /dev/null
@@ -0,0 +1,112 @@
+From stable+bounces-267220-greg=kroah.com@vger.kernel.org Thu Jun 18 21:17:07 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:35 -0400
+Subject: ftrace: Have ftrace pages output reflect freed pages
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <5773e8c00a533a29c89b42522a16f2742b97c3af.1781809974.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 264143c4e54412095f4b615e65bf736fc3c60af0 ]
+
+The amount of memory that ftrace uses to save the descriptors to manage
+the functions it can trace is shown at output. But if there are a lot of
+functions that are skipped because they were weak or the architecture
+added holes into the tables, then the extra pages that were allocated are
+freed. But these freed pages are not reflected in the numbers shown, and
+they can even be inconsistent with what is reported:
+
+ ftrace: allocating 57482 entries in 225 pages
+ ftrace: allocated 224 pages with 3 groups
+
+The above shows the number of original entries that are in the mcount_loc
+section and the pages needed to save them (225), but the second output
+reflects the number of pages that were actually used. The two should be
+consistent as:
+
+ ftrace: allocating 56739 entries in 224 pages
+ ftrace: allocated 224 pages with 3 groups
+
+The above also shows the accurate number of entires that were actually
+stored and does not include the entries that were removed.
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Heiko Carstens <hca@linux.ibm.com>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: Vasily Gorbik <gor@linux.ibm.com>
+Cc: Alexander Gordeev <agordeev@linux.ibm.com>
+Link: https://lore.kernel.org/20250218200023.221100846@goodmis.org
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/ftrace.c |   15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+--- a/kernel/trace/ftrace.c
++++ b/kernel/trace/ftrace.c
+@@ -7050,6 +7050,7 @@ static int ftrace_process_locs(struct mo
+       unsigned long addr;
+       unsigned long kaslr;
+       unsigned long flags = 0; /* Shut up gcc */
++      unsigned long pages;
+       int ret = -ENOMEM;
+       count = end - start;
+@@ -7057,6 +7058,8 @@ static int ftrace_process_locs(struct mo
+       if (!count)
+               return 0;
++      pages = DIV_ROUND_UP(count, ENTRIES_PER_PAGE);
++
+       /*
+        * Sorting mcount in vmlinux at build time depend on
+        * CONFIG_BUILDTIME_MCOUNT_SORT, while mcount loc in
+@@ -7168,6 +7171,8 @@ static int ftrace_process_locs(struct mo
+                       for (pg = pg_unuse; pg; pg = pg->next)
+                               remaining += 1 << pg->order;
++                      pages -= remaining;
++
+                       skip = DIV_ROUND_UP(skip, ENTRIES_PER_PAGE);
+                       /*
+@@ -7181,6 +7186,13 @@ static int ftrace_process_locs(struct mo
+               synchronize_rcu();
+               ftrace_free_pages(pg_unuse);
+       }
++
++      if (!mod) {
++              count -= skipped;
++              pr_info("ftrace: allocating %ld entries in %ld pages\n",
++                      count, pages);
++      }
++
+       return ret;
+ }
+@@ -7835,9 +7847,6 @@ void __init ftrace_init(void)
+               goto failed;
+       }
+-      pr_info("ftrace: allocating %ld entries in %ld pages\n",
+-              count, DIV_ROUND_UP(count, ENTRIES_PER_PAGE));
+-
+       ret = ftrace_process_locs(NULL,
+                                 __start_mcount_loc,
+                                 __stop_mcount_loc);
diff --git a/queue-6.12/ftrace-test-mcount_loc-addr-before-calling-ftrace_call_addr.patch b/queue-6.12/ftrace-test-mcount_loc-addr-before-calling-ftrace_call_addr.patch
new file mode 100644 (file)
index 0000000..fe8b402
--- /dev/null
@@ -0,0 +1,62 @@
+From stable+bounces-267223-greg=kroah.com@vger.kernel.org Thu Jun 18 21:17:30 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:37 -0400
+Subject: ftrace: Test mcount_loc addr before calling ftrace_call_addr()
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <0e6f0c263a1c1b93f1fa6ae5310225e1e7300cde.1781809979.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 6eeca746fa5f1dd03c6ee05cb03f5eb1ddda1c81 ]
+
+The addresses in the mcount_loc can be zeroed and then moved by KASLR
+making them invalid addresses. ftrace_call_addr() for ARM 64 expects a
+valid address to kernel text. If the addr read from the mcount_loc section
+is invalid, it must not call ftrace_call_addr(). Move the addr check
+before calling ftrace_call_addr() in ftrace_process_locs().
+
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/20250225182054.290128736@goodmis.org
+Fixes: ef378c3b8233 ("scripts/sorttable: Zero out weak functions in mcount_loc table")
+Reported-by: Nathan Chancellor <nathan@kernel.org>
+Reported-by: "Arnd Bergmann" <arnd@arndb.de>
+Tested-by: Nathan Chancellor <nathan@kernel.org>
+Closes: https://lore.kernel.org/all/20250225025631.GA271248@ax162/
+Closes: https://lore.kernel.org/all/91523154-072b-437b-bbdc-0b70e9783fd0@app.fastmail.com/
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/ftrace.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/kernel/trace/ftrace.c
++++ b/kernel/trace/ftrace.c
+@@ -7108,7 +7108,9 @@ static int ftrace_process_locs(struct mo
+       pg = start_pg;
+       while (p < end) {
+               unsigned long end_offset;
+-              addr = ftrace_call_adjust(*p++);
++
++              addr = *p++;
++
+               /*
+                * Some architecture linkers will pad between
+                * the different mcount_loc sections of different
+@@ -7120,6 +7122,8 @@ static int ftrace_process_locs(struct mo
+                       continue;
+               }
++              addr = ftrace_call_adjust(addr);
++
+               end_offset = (pg->index+1) * sizeof(pg->records[0]);
+               if (end_offset > PAGE_SIZE << pg->order) {
+                       /* We should have allocated enough */
diff --git a/queue-6.12/ftrace-update-the-mcount_loc-check-of-skipped-entries.patch b/queue-6.12/ftrace-update-the-mcount_loc-check-of-skipped-entries.patch
new file mode 100644 (file)
index 0000000..bbf2731
--- /dev/null
@@ -0,0 +1,75 @@
+From stable+bounces-267221-greg=kroah.com@vger.kernel.org Thu Jun 18 21:17:10 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:34 -0400
+Subject: ftrace: Update the mcount_loc check of skipped entries
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <60ec429dd94faa00507cc8f10127ee80a89bd2d9.1781809971.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 4a3efc6baff931da9a85c6d2e42c87bd9a827399 ]
+
+Now that weak functions turn into skipped entries, update the check to
+make sure the amount that was allocated would fit both the entries that
+were allocated as well as those that were skipped.
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Heiko Carstens <hca@linux.ibm.com>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: Vasily Gorbik <gor@linux.ibm.com>
+Cc: Alexander Gordeev <agordeev@linux.ibm.com>
+Link: https://lore.kernel.org/20250218200023.055162048@goodmis.org
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/ftrace.c |   23 ++++++++++++++++++++++-
+ 1 file changed, 22 insertions(+), 1 deletion(-)
+
+--- a/kernel/trace/ftrace.c
++++ b/kernel/trace/ftrace.c
+@@ -7155,7 +7155,28 @@ static int ftrace_process_locs(struct mo
+       /* We should have used all pages unless we skipped some */
+       if (pg_unuse) {
+-              WARN_ON(!skipped);
++              unsigned long pg_remaining, remaining = 0;
++              unsigned long skip;
++
++              /* Count the number of entries unused and compare it to skipped. */
++              pg_remaining = (ENTRIES_PER_PAGE << pg->order) - pg->index;
++
++              if (!WARN(skipped < pg_remaining, "Extra allocated pages for ftrace")) {
++
++                      skip = skipped - pg_remaining;
++
++                      for (pg = pg_unuse; pg; pg = pg->next)
++                              remaining += 1 << pg->order;
++
++                      skip = DIV_ROUND_UP(skip, ENTRIES_PER_PAGE);
++
++                      /*
++                       * Check to see if the number of pages remaining would
++                       * just fit the number of entries skipped.
++                       */
++                      WARN(skip != remaining, "Extra allocated pages for ftrace: %lu with %lu skipped",
++                           remaining, skipped);
++              }
+               /* Need to synchronize with ftrace_location_range() */
+               synchronize_rcu();
+               ftrace_free_pages(pg_unuse);
diff --git a/queue-6.12/net-ipv6-make-udp_tunnel6_xmit_skb-void.patch b/queue-6.12/net-ipv6-make-udp_tunnel6_xmit_skb-void.patch
new file mode 100644 (file)
index 0000000..4d42dd2
--- /dev/null
@@ -0,0 +1,138 @@
+From stable+bounces-268302-greg=kroah.com@vger.kernel.org Thu Jun 25 09:28:55 2026
+From: Alexander Martyniuk <alexevgmart@gmail.com>
+Date: Thu, 25 Jun 2026 11:24:41 +0300
+Subject: net: ipv6: Make udp_tunnel6_xmit_skb() void
+To: stable@vger.kernel.org, gregkh@linuxfoundation.org
+Cc: Alexander Martyniuk <alexevgmart@gmail.com>, "David S. Miller" <davem@davemloft.net>, Eric Dumazet <edumazet@google.com>, Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>, David Ahern <dsahern@kernel.org>, Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>, Xin Long <lucien.xin@gmail.com>, Jon Maloy <jmaloy@redhat.com>, Ying Xue <ying.xue@windriver.com>, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-sctp@vger.kernel.org, tipc-discussion@lists.sourceforge.net, Petr Machata <petrm@nvidia.com>, Ido Schimmel <idosch@nvidia.com>, Nikolay Aleksandrov <razor@blackwall.org>
+Message-ID: <20260625082442.96390-2-alexevgmart@gmail.com>
+
+From: Petr Machata <petrm@nvidia.com>
+
+commit 6a7d88ca15f73c5c570c372238f71d63da1fda55 upstream.
+
+The function always returns zero, thus the return value does not carry any
+signal. Just make it void.
+
+Most callers already ignore the return value. However:
+
+- Refold arguments of the call from sctp_v6_xmit() so that they fit into
+  the 80-column limit.
+
+- tipc_udp_xmit() initializes err from the return value, but that should
+  already be always zero at that point. So there's no practical change, but
+  elision of the assignment prompts a couple more tweaks to clean up the
+  function.
+
+Signed-off-by: Petr Machata <petrm@nvidia.com>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
+Link: https://patch.msgid.link/7facacf9d8ca3ca9391a4aee88160913671b868d.1750113335.git.petrm@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Alexander Martyniuk <alexevgmart@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/udp_tunnel.h  |   14 +++++++-------
+ net/ipv6/ip6_udp_tunnel.c |   15 +++++++--------
+ net/sctp/ipv6.c           |    7 ++++---
+ net/tipc/udp_media.c      |   10 +++++-----
+ 4 files changed, 23 insertions(+), 23 deletions(-)
+
+--- a/include/net/udp_tunnel.h
++++ b/include/net/udp_tunnel.h
+@@ -152,13 +152,13 @@ void udp_tunnel_xmit_skb(struct rtable *
+                        __be16 df, __be16 src_port, __be16 dst_port,
+                        bool xnet, bool nocheck);
+-int udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sock *sk,
+-                       struct sk_buff *skb,
+-                       struct net_device *dev,
+-                       const struct in6_addr *saddr,
+-                       const struct in6_addr *daddr,
+-                       __u8 prio, __u8 ttl, __be32 label,
+-                       __be16 src_port, __be16 dst_port, bool nocheck);
++void udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sock *sk,
++                        struct sk_buff *skb,
++                        struct net_device *dev,
++                        const struct in6_addr *saddr,
++                        const struct in6_addr *daddr,
++                        __u8 prio, __u8 ttl, __be32 label,
++                        __be16 src_port, __be16 dst_port, bool nocheck);
+ void udp_tunnel_sock_release(struct socket *sock);
+--- a/net/ipv6/ip6_udp_tunnel.c
++++ b/net/ipv6/ip6_udp_tunnel.c
+@@ -74,13 +74,13 @@ error:
+ }
+ EXPORT_SYMBOL_GPL(udp_sock_create6);
+-int udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sock *sk,
+-                       struct sk_buff *skb,
+-                       struct net_device *dev,
+-                       const struct in6_addr *saddr,
+-                       const struct in6_addr *daddr,
+-                       __u8 prio, __u8 ttl, __be32 label,
+-                       __be16 src_port, __be16 dst_port, bool nocheck)
++void udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sock *sk,
++                        struct sk_buff *skb,
++                        struct net_device *dev,
++                        const struct in6_addr *saddr,
++                        const struct in6_addr *daddr,
++                        __u8 prio, __u8 ttl, __be32 label,
++                        __be16 src_port, __be16 dst_port, bool nocheck)
+ {
+       struct udphdr *uh;
+       struct ipv6hdr *ip6h;
+@@ -109,7 +109,6 @@ int udp_tunnel6_xmit_skb(struct dst_entr
+       ip6h->saddr       = *saddr;
+       ip6tunnel_xmit(sk, skb, dev);
+-      return 0;
+ }
+ EXPORT_SYMBOL_GPL(udp_tunnel6_xmit_skb);
+--- a/net/sctp/ipv6.c
++++ b/net/sctp/ipv6.c
+@@ -261,9 +261,10 @@ static int sctp_v6_xmit(struct sk_buff *
+       skb_set_inner_ipproto(skb, IPPROTO_SCTP);
+       label = ip6_make_flowlabel(sock_net(sk), skb, fl6->flowlabel, true, fl6);
+-      return udp_tunnel6_xmit_skb(dst, sk, skb, NULL, &fl6->saddr,
+-                                  &fl6->daddr, tclass, ip6_dst_hoplimit(dst),
+-                                  label, sctp_sk(sk)->udp_port, t->encap_port, false);
++      udp_tunnel6_xmit_skb(dst, sk, skb, NULL, &fl6->saddr, &fl6->daddr,
++                           tclass, ip6_dst_hoplimit(dst), label,
++                           sctp_sk(sk)->udp_port, t->encap_port, false);
++      return 0;
+ }
+ /* Returns the dst cache entry for the given source and destination ip
+--- a/net/tipc/udp_media.c
++++ b/net/tipc/udp_media.c
+@@ -172,7 +172,7 @@ static int tipc_udp_xmit(struct net *net
+                        struct udp_media_addr *dst, struct dst_cache *cache)
+ {
+       struct dst_entry *ndst;
+-      int ttl, err = 0;
++      int ttl, err;
+       local_bh_disable();
+       ndst = dst_cache_get(cache);
+@@ -217,13 +217,13 @@ static int tipc_udp_xmit(struct net *net
+                       dst_cache_set_ip6(cache, ndst, &fl6.saddr);
+               }
+               ttl = ip6_dst_hoplimit(ndst);
+-              err = udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, NULL,
+-                                         &src->ipv6, &dst->ipv6, 0, ttl, 0,
+-                                         src->port, dst->port, false);
++              udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, NULL,
++                                   &src->ipv6, &dst->ipv6, 0, ttl, 0,
++                                   src->port, dst->port, false);
+ #endif
+       }
+       local_bh_enable();
+-      return err;
++      return 0;
+ tx_error:
+       local_bh_enable();
diff --git a/queue-6.12/scripts-sorttable-add-helper-functions-for-elf_ehdr.patch b/queue-6.12/scripts-sorttable-add-helper-functions-for-elf_ehdr.patch
new file mode 100644 (file)
index 0000000..94b5378
--- /dev/null
@@ -0,0 +1,135 @@
+From prvs=262951c835=andrey.grodzovsky@crowdstrike.com Thu Jun 18 21:16:01 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:23 -0400
+Subject: scripts/sorttable: Add helper functions for Elf_Ehdr
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <0cc98e948927e588c76a9a6a8b695ceb74259c1f.1781809936.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 1dfb59a228dde59ad7d99b2fa2104e90004995c7 ]
+
+In order to remove the double #include of sorttable.h for 64 and 32 bit
+to create duplicate functions, add helper functions for Elf_Ehdr.  This
+will create a function pointer for each helper that will get assigned to
+the appropriate function to handle either the 64bit or 32bit version.
+
+This also moves the _r()/r() wrappers for the Elf_Ehdr references that
+handle endian and size differences between the different architectures,
+into the helper function and out of the open code which is more error
+prone.
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Link: https://lore.kernel.org/20250105162345.736369526@goodmis.org
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.c |   25 +++++++++++++++++++++++++
+ scripts/sorttable.h |   20 ++++++++++++++++----
+ 2 files changed, 41 insertions(+), 4 deletions(-)
+
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -85,6 +85,31 @@ static uint64_t (*r8)(const uint64_t *);
+ static void (*w)(uint32_t, uint32_t *);
+ typedef void (*table_sort_t)(char *, int);
++static uint64_t ehdr64_shoff(Elf_Ehdr *ehdr)
++{
++      return r8(&ehdr->e64.e_shoff);
++}
++
++static uint64_t ehdr32_shoff(Elf_Ehdr *ehdr)
++{
++      return r(&ehdr->e32.e_shoff);
++}
++
++#define EHDR_HALF(fn_name)                            \
++static uint16_t ehdr64_##fn_name(Elf_Ehdr *ehdr)      \
++{                                                     \
++      return r2(&ehdr->e64.e_##fn_name);              \
++}                                                     \
++                                                      \
++static uint16_t ehdr32_##fn_name(Elf_Ehdr *ehdr)      \
++{                                                     \
++      return r2(&ehdr->e32.e_##fn_name);              \
++}
++
++EHDR_HALF(shentsize)
++EHDR_HALF(shstrndx)
++EHDR_HALF(shnum)
++
+ /*
+  * Get the whole file as a programming convenience in order to avoid
+  * malloc+lseek+read+free of many pieces.  If successful, then mmap
+--- a/scripts/sorttable.h
++++ b/scripts/sorttable.h
+@@ -27,6 +27,10 @@
+ #undef uint_t
+ #undef _r
+ #undef etype
++#undef ehdr_shoff
++#undef ehdr_shentsize
++#undef ehdr_shstrndx
++#undef ehdr_shnum
+ #ifdef SORTTABLE_64
+ # define extable_ent_size     16
+@@ -39,6 +43,10 @@
+ # define uint_t                       uint64_t
+ # define _r                   r8
+ # define etype                        e64
++# define ehdr_shoff           ehdr64_shoff
++# define ehdr_shentsize               ehdr64_shentsize
++# define ehdr_shstrndx                ehdr64_shstrndx
++# define ehdr_shnum           ehdr64_shnum
+ #else
+ # define extable_ent_size     8
+ # define compare_extable      compare_extable_32
+@@ -50,6 +58,10 @@
+ # define uint_t                       uint32_t
+ # define _r                   r
+ # define etype                        e32
++# define ehdr_shoff           ehdr32_shoff
++# define ehdr_shentsize               ehdr32_shentsize
++# define ehdr_shstrndx                ehdr32_shstrndx
++# define ehdr_shnum           ehdr32_shnum
+ #endif
+ #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+@@ -250,16 +262,16 @@ static int do_sort(Elf_Ehdr *ehdr,
+       unsigned int orc_num_entries = 0;
+ #endif
+-      shdr_start = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->etype.e_shoff));
+-      shentsize = r2(&ehdr->etype.e_shentsize);
++      shdr_start = (Elf_Shdr *)((char *)ehdr + ehdr_shoff(ehdr));
++      shentsize = ehdr_shentsize(ehdr);
+-      shstrndx = r2(&ehdr->etype.e_shstrndx);
++      shstrndx = ehdr_shstrndx(ehdr);
+       if (shstrndx == SHN_XINDEX)
+               shstrndx = r(&shdr_start->etype.sh_link);
+       string_sec = get_index(shdr_start, shentsize, shstrndx);
+       secstrings = (const char *)ehdr + _r(&string_sec->etype.sh_offset);
+-      shnum = r2(&ehdr->etype.e_shnum);
++      shnum = ehdr_shnum(ehdr);
+       if (shnum == SHN_UNDEF)
+               shnum = _r(&shdr_start->etype.sh_size);
diff --git a/queue-6.12/scripts-sorttable-add-helper-functions-for-elf_shdr.patch b/queue-6.12/scripts-sorttable-add-helper-functions-for-elf_shdr.patch
new file mode 100644 (file)
index 0000000..a84fd3d
--- /dev/null
@@ -0,0 +1,249 @@
+From stable+bounces-267211-greg=kroah.com@vger.kernel.org Thu Jun 18 21:16:11 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:24 -0400
+Subject: scripts/sorttable: Add helper functions for Elf_Shdr
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <67462057b3867a75adaa8de9b8a091c2787f7735.1781809940.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 67afb7f504400e5b4e5ff895459fbb3eb63d4450 ]
+
+In order to remove the double #include of sorttable.h for 64 and 32 bit
+to create duplicate functions, add helper functions for Elf_Shdr.  This
+will create a function pointer for each helper that will get assigned to
+the appropriate function to handle either the 64bit or 32bit version.
+
+This also moves the _r()/r() wrappers for the Elf_Shdr references that
+handle endian and size differences between the different architectures,
+into the helper function and out of the open code which is more error
+prone.
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Link: https://lore.kernel.org/20250105162345.940924221@goodmis.org
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.c |   42 +++++++++++++++++++++++++++++++++
+ scripts/sorttable.h |   66 +++++++++++++++++++++++++++++++++-------------------
+ 2 files changed, 85 insertions(+), 23 deletions(-)
+
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -110,6 +110,48 @@ EHDR_HALF(shentsize)
+ EHDR_HALF(shstrndx)
+ EHDR_HALF(shnum)
++#define SHDR_WORD(fn_name)                            \
++static uint32_t shdr64_##fn_name(Elf_Shdr *shdr)      \
++{                                                     \
++      return r(&shdr->e64.sh_##fn_name);              \
++}                                                     \
++                                                      \
++static uint32_t shdr32_##fn_name(Elf_Shdr *shdr)      \
++{                                                     \
++      return r(&shdr->e32.sh_##fn_name);              \
++}
++
++#define SHDR_ADDR(fn_name)                            \
++static uint64_t shdr64_##fn_name(Elf_Shdr *shdr)      \
++{                                                     \
++      return r8(&shdr->e64.sh_##fn_name);             \
++}                                                     \
++                                                      \
++static uint64_t shdr32_##fn_name(Elf_Shdr *shdr)      \
++{                                                     \
++      return r(&shdr->e32.sh_##fn_name);              \
++}
++
++#define SHDR_WORD(fn_name)                            \
++static uint32_t shdr64_##fn_name(Elf_Shdr *shdr)      \
++{                                                     \
++      return r(&shdr->e64.sh_##fn_name);              \
++}                                                     \
++                                                      \
++static uint32_t shdr32_##fn_name(Elf_Shdr *shdr)      \
++{                                                     \
++      return r(&shdr->e32.sh_##fn_name);              \
++}
++
++SHDR_ADDR(addr)
++SHDR_ADDR(offset)
++SHDR_ADDR(size)
++SHDR_ADDR(entsize)
++
++SHDR_WORD(link)
++SHDR_WORD(name)
++SHDR_WORD(type)
++
+ /*
+  * Get the whole file as a programming convenience in order to avoid
+  * malloc+lseek+read+free of many pieces.  If successful, then mmap
+--- a/scripts/sorttable.h
++++ b/scripts/sorttable.h
+@@ -31,6 +31,13 @@
+ #undef ehdr_shentsize
+ #undef ehdr_shstrndx
+ #undef ehdr_shnum
++#undef shdr_addr
++#undef shdr_offset
++#undef shdr_link
++#undef shdr_size
++#undef shdr_name
++#undef shdr_type
++#undef shdr_entsize
+ #ifdef SORTTABLE_64
+ # define extable_ent_size     16
+@@ -47,6 +54,13 @@
+ # define ehdr_shentsize               ehdr64_shentsize
+ # define ehdr_shstrndx                ehdr64_shstrndx
+ # define ehdr_shnum           ehdr64_shnum
++# define shdr_addr            shdr64_addr
++# define shdr_offset          shdr64_offset
++# define shdr_link            shdr64_link
++# define shdr_size            shdr64_size
++# define shdr_name            shdr64_name
++# define shdr_type            shdr64_type
++# define shdr_entsize         shdr64_entsize
+ #else
+ # define extable_ent_size     8
+ # define compare_extable      compare_extable_32
+@@ -62,6 +76,13 @@
+ # define ehdr_shentsize               ehdr32_shentsize
+ # define ehdr_shstrndx                ehdr32_shstrndx
+ # define ehdr_shnum           ehdr32_shnum
++# define shdr_addr            shdr32_addr
++# define shdr_offset          shdr32_offset
++# define shdr_link            shdr32_link
++# define shdr_size            shdr32_size
++# define shdr_name            shdr32_name
++# define shdr_type            shdr32_type
++# define shdr_entsize         shdr32_entsize
+ #endif
+ #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+@@ -177,8 +198,8 @@ struct elf_mcount_loc {
+ static void *sort_mcount_loc(void *arg)
+ {
+       struct elf_mcount_loc *emloc = (struct elf_mcount_loc *)arg;
+-      uint_t offset = emloc->start_mcount_loc - _r(&(emloc->init_data_sec)->etype.sh_addr)
+-                                      + _r(&(emloc->init_data_sec)->etype.sh_offset);
++      uint_t offset = emloc->start_mcount_loc - shdr_addr(emloc->init_data_sec)
++                                      + shdr_offset(emloc->init_data_sec);
+       uint_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc;
+       unsigned char *start_loc = (void *)emloc->ehdr + offset;
+@@ -267,18 +288,18 @@ static int do_sort(Elf_Ehdr *ehdr,
+       shstrndx = ehdr_shstrndx(ehdr);
+       if (shstrndx == SHN_XINDEX)
+-              shstrndx = r(&shdr_start->etype.sh_link);
++              shstrndx = shdr_link(shdr_start);
+       string_sec = get_index(shdr_start, shentsize, shstrndx);
+-      secstrings = (const char *)ehdr + _r(&string_sec->etype.sh_offset);
++      secstrings = (const char *)ehdr + shdr_offset(string_sec);
+       shnum = ehdr_shnum(ehdr);
+       if (shnum == SHN_UNDEF)
+-              shnum = _r(&shdr_start->etype.sh_size);
++              shnum = shdr_size(shdr_start);
+       for (i = 0; i < shnum; i++) {
+               Elf_Shdr *shdr = get_index(shdr_start, shentsize, i);
+-              idx = r(&shdr->etype.sh_name);
++              idx = shdr_name(shdr);
+               if (!strcmp(secstrings + idx, "__ex_table"))
+                       extab_sec = shdr;
+               if (!strcmp(secstrings + idx, ".symtab"))
+@@ -286,9 +307,9 @@ static int do_sort(Elf_Ehdr *ehdr,
+               if (!strcmp(secstrings + idx, ".strtab"))
+                       strtab_sec = shdr;
+-              if (r(&shdr->etype.sh_type) == SHT_SYMTAB_SHNDX)
++              if (shdr_type(shdr) == SHT_SYMTAB_SHNDX)
+                       symtab_shndx = (Elf32_Word *)((const char *)ehdr +
+-                                                    _r(&shdr->etype.sh_offset));
++                                                    shdr_offset(shdr));
+ #ifdef MCOUNT_SORT_ENABLED
+               /* locate the .init.data section in vmlinux */
+@@ -304,14 +325,14 @@ static int do_sort(Elf_Ehdr *ehdr,
+ #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+               /* locate the ORC unwind tables */
+               if (!strcmp(secstrings + idx, ".orc_unwind_ip")) {
+-                      orc_ip_size = _r(&shdr->etype.sh_size);
++                      orc_ip_size = shdr_size(shdr);
+                       g_orc_ip_table = (int *)((void *)ehdr +
+-                                                 _r(&shdr->etype.sh_offset));
++                                                 shdr_offset(shdr));
+               }
+               if (!strcmp(secstrings + idx, ".orc_unwind")) {
+-                      orc_size = _r(&shdr->etype.sh_size);
++                      orc_size = shdr_size(shdr);
+                       g_orc_table = (struct orc_entry *)((void *)ehdr +
+-                                                           _r(&shdr->etype.sh_offset));
++                                                           shdr_offset(shdr));
+               }
+ #endif
+       } /* for loop */
+@@ -374,23 +395,22 @@ static int do_sort(Elf_Ehdr *ehdr,
+               goto out;
+       }
+-      extab_image = (void *)ehdr + _r(&extab_sec->etype.sh_offset);
+-      strtab = (const char *)ehdr + _r(&strtab_sec->etype.sh_offset);
+-      symtab = (const Elf_Sym *)((const char *)ehdr +
+-                                                _r(&symtab_sec->etype.sh_offset));
++      extab_image = (void *)ehdr + shdr_offset(extab_sec);
++      strtab = (const char *)ehdr + shdr_offset(strtab_sec);
++      symtab = (const Elf_Sym *)((const char *)ehdr + shdr_offset(symtab_sec));
+       if (custom_sort) {
+-              custom_sort(extab_image, _r(&extab_sec->etype.sh_size));
++              custom_sort(extab_image, shdr_size(extab_sec));
+       } else {
+-              int num_entries = _r(&extab_sec->etype.sh_size) / extable_ent_size;
++              int num_entries = shdr_size(extab_sec) / extable_ent_size;
+               qsort(extab_image, num_entries,
+                     extable_ent_size, compare_extable);
+       }
+       /* find the flag main_extable_sort_needed */
+-      sym_start = (void *)ehdr + _r(&symtab_sec->etype.sh_offset);
+-      sym_end = sym_start + _r(&symtab_sec->etype.sh_size);
+-      symentsize = _r(&symtab_sec->etype.sh_entsize);
++      sym_start = (void *)ehdr + shdr_offset(symtab_sec);
++      sym_end = sym_start + shdr_size(symtab_sec);
++      symentsize = shdr_entsize(symtab_sec);
+       for (sym = sym_start; (void *)sym + symentsize < sym_end;
+            sym = (void *)sym + symentsize) {
+@@ -415,9 +435,9 @@ static int do_sort(Elf_Ehdr *ehdr,
+                                      symtab_shndx);
+       sort_needed_sec = get_index(shdr_start, shentsize, sort_need_index);
+       sort_needed_loc = (void *)ehdr +
+-              _r(&sort_needed_sec->etype.sh_offset) +
++              shdr_offset(sort_needed_sec) +
+               _r(&sort_needed_sym->etype.st_value) -
+-              _r(&sort_needed_sec->etype.sh_addr);
++              shdr_addr(sort_needed_sec);
+       /* extable has been sorted, clear the flag */
+       w(0, sort_needed_loc);
diff --git a/queue-6.12/scripts-sorttable-add-helper-functions-for-elf_sym.patch b/queue-6.12/scripts-sorttable-add-helper-functions-for-elf_sym.patch
new file mode 100644 (file)
index 0000000..28c6b6c
--- /dev/null
@@ -0,0 +1,199 @@
+From prvs=262951c835=andrey.grodzovsky@crowdstrike.com Thu Jun 18 21:16:03 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:25 -0400
+Subject: scripts/sorttable: Add helper functions for Elf_Sym
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <3ef7d2f3e8d9dc192663d7270f7ecd41e78c80e1.1781809943.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 17bed33ac12f011f4695059960e1b1d6457229a7 ]
+
+In order to remove the double #include of sorttable.h for 64 and 32 bit
+to create duplicate functions, add helper functions for Elf_Sym.  This
+will create a function pointer for each helper that will get assigned to
+the appropriate function to handle either the 64bit or 32bit version.
+
+This also removes the last references of etype and _r() macros from the
+sorttable.h file as their references are now just defined in the
+appropriate architecture version of the helper functions. All read
+functions now exist in the helper functions which makes it easier to
+maintain, as the helper functions define the necessary architecture sizes.
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Link: https://lore.kernel.org/20250105162346.185740651@goodmis.org
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.c |   47 +++++++++++++++++++++++++++++++++++++++++++++++
+ scripts/sorttable.h |   30 ++++++++++++++++--------------
+ 2 files changed, 63 insertions(+), 14 deletions(-)
+
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -152,6 +152,53 @@ SHDR_WORD(link)
+ SHDR_WORD(name)
+ SHDR_WORD(type)
++#define SYM_ADDR(fn_name)                     \
++static uint64_t sym64_##fn_name(Elf_Sym *sym) \
++{                                             \
++      return r8(&sym->e64.st_##fn_name);      \
++}                                             \
++                                              \
++static uint64_t sym32_##fn_name(Elf_Sym *sym) \
++{                                             \
++      return r(&sym->e32.st_##fn_name);       \
++}
++
++#define SYM_WORD(fn_name)                     \
++static uint32_t sym64_##fn_name(Elf_Sym *sym) \
++{                                             \
++      return r(&sym->e64.st_##fn_name);       \
++}                                             \
++                                              \
++static uint32_t sym32_##fn_name(Elf_Sym *sym) \
++{                                             \
++      return r(&sym->e32.st_##fn_name);       \
++}
++
++#define SYM_HALF(fn_name)                     \
++static uint16_t sym64_##fn_name(Elf_Sym *sym) \
++{                                             \
++      return r2(&sym->e64.st_##fn_name);      \
++}                                             \
++                                              \
++static uint16_t sym32_##fn_name(Elf_Sym *sym) \
++{                                             \
++      return r2(&sym->e32.st_##fn_name);      \
++}
++
++static uint8_t sym64_type(Elf_Sym *sym)
++{
++      return ELF64_ST_TYPE(sym->e64.st_info);
++}
++
++static uint8_t sym32_type(Elf_Sym *sym)
++{
++      return ELF32_ST_TYPE(sym->e32.st_info);
++}
++
++SYM_ADDR(value)
++SYM_WORD(name)
++SYM_HALF(shndx)
++
+ /*
+  * Get the whole file as a programming convenience in order to avoid
+  * malloc+lseek+read+free of many pieces.  If successful, then mmap
+--- a/scripts/sorttable.h
++++ b/scripts/sorttable.h
+@@ -23,10 +23,7 @@
+ #undef sort_mcount_loc
+ #undef elf_mcount_loc
+ #undef do_sort
+-#undef ELF_ST_TYPE
+ #undef uint_t
+-#undef _r
+-#undef etype
+ #undef ehdr_shoff
+ #undef ehdr_shentsize
+ #undef ehdr_shstrndx
+@@ -38,6 +35,10 @@
+ #undef shdr_name
+ #undef shdr_type
+ #undef shdr_entsize
++#undef sym_type
++#undef sym_name
++#undef sym_value
++#undef sym_shndx
+ #ifdef SORTTABLE_64
+ # define extable_ent_size     16
+@@ -46,10 +47,7 @@
+ # define sort_mcount_loc      sort_mcount_loc_64
+ # define elf_mcount_loc               elf_mcount_loc_64
+ # define do_sort              do_sort_64
+-# define ELF_ST_TYPE          ELF64_ST_TYPE
+ # define uint_t                       uint64_t
+-# define _r                   r8
+-# define etype                        e64
+ # define ehdr_shoff           ehdr64_shoff
+ # define ehdr_shentsize               ehdr64_shentsize
+ # define ehdr_shstrndx                ehdr64_shstrndx
+@@ -61,6 +59,10 @@
+ # define shdr_name            shdr64_name
+ # define shdr_type            shdr64_type
+ # define shdr_entsize         shdr64_entsize
++# define sym_type             sym64_type
++# define sym_name             sym64_name
++# define sym_value            sym64_value
++# define sym_shndx            sym64_shndx
+ #else
+ # define extable_ent_size     8
+ # define compare_extable      compare_extable_32
+@@ -68,10 +70,7 @@
+ # define sort_mcount_loc      sort_mcount_loc_32
+ # define elf_mcount_loc               elf_mcount_loc_32
+ # define do_sort              do_sort_32
+-# define ELF_ST_TYPE          ELF32_ST_TYPE
+ # define uint_t                       uint32_t
+-# define _r                   r
+-# define etype                        e32
+ # define ehdr_shoff           ehdr32_shoff
+ # define ehdr_shentsize               ehdr32_shentsize
+ # define ehdr_shstrndx                ehdr32_shstrndx
+@@ -83,6 +82,10 @@
+ # define shdr_name            shdr32_name
+ # define shdr_type            shdr32_type
+ # define shdr_entsize         shdr32_entsize
++# define sym_type             sym32_type
++# define sym_name             sym32_name
++# define sym_value            sym32_value
++# define sym_shndx            sym32_shndx
+ #endif
+ #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+@@ -414,9 +417,9 @@ static int do_sort(Elf_Ehdr *ehdr,
+       for (sym = sym_start; (void *)sym + symentsize < sym_end;
+            sym = (void *)sym + symentsize) {
+-              if (ELF_ST_TYPE(sym->etype.st_info) != STT_OBJECT)
++              if (sym_type(sym) != STT_OBJECT)
+                       continue;
+-              if (!strcmp(strtab + r(&sym->etype.st_name),
++              if (!strcmp(strtab + sym_name(sym),
+                           "main_extable_sort_needed")) {
+                       sort_needed_sym = sym;
+                       break;
+@@ -430,14 +433,13 @@ static int do_sort(Elf_Ehdr *ehdr,
+               goto out;
+       }
+-      sort_need_index = get_secindex(r2(&sym->etype.st_shndx),
++      sort_need_index = get_secindex(sym_shndx(sym),
+                                      ((void *)sort_needed_sym - (void *)symtab) / symentsize,
+                                      symtab_shndx);
+       sort_needed_sec = get_index(shdr_start, shentsize, sort_need_index);
+       sort_needed_loc = (void *)ehdr +
+               shdr_offset(sort_needed_sec) +
+-              _r(&sort_needed_sym->etype.st_value) -
+-              shdr_addr(sort_needed_sec);
++              sym_value(sort_needed_sym) - shdr_addr(sort_needed_sec);
+       /* extable has been sorted, clear the flag */
+       w(0, sort_needed_loc);
diff --git a/queue-6.12/scripts-sorttable-allow-matches-to-functions-before-function-entry.patch b/queue-6.12/scripts-sorttable-allow-matches-to-functions-before-function-entry.patch
new file mode 100644 (file)
index 0000000..b170bd4
--- /dev/null
@@ -0,0 +1,69 @@
+From stable+bounces-267226-greg=kroah.com@vger.kernel.org Thu Jun 18 21:17:53 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:40 -0400
+Subject: scripts/sorttable: Allow matches to functions before function entry
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <7b17ef2d6c2be58e80c028343547c67c81de3d56.1781809987.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit dc208c69c033d3caba0509da1ae065d2b5ff165f ]
+
+ARM 64 uses -fpatchable-function-entry=4,2 which adds padding before the
+function and the addresses in the mcount_loc point there instead of the
+function entry that is returned by nm. In order to find a function from nm
+to make sure it's not an unused weak function, the entries in the
+mcount_loc section needs to match the entries from nm. Since it can be an
+instruction before the entry, add a before_func variable that ARM 64 can
+set to 8, and if the mcount_loc entry is within 8 bytes of the nm function
+entry, then it will be considered a match.
+
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: "Arnd Bergmann" <arnd@arndb.de>
+Cc: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/20250225182054.815536219@goodmis.org
+Fixes: ef378c3b82338 ("scripts/sorttable: Zero out weak functions in mcount_loc table")
+Tested-by: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.c |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -611,13 +611,16 @@ static int add_field(uint64_t addr, uint
+       return 0;
+ }
++/* Used for when mcount/fentry is before the function entry */
++static int before_func;
++
+ /* Only return match if the address lies inside the function size */
+ static int cmp_func_addr(const void *K, const void *A)
+ {
+       uint64_t key = *(const uint64_t *)K;
+       const struct func_info *a = A;
+-      if (key < a->addr)
++      if (key + before_func < a->addr)
+               return -1;
+       return key >= a->addr + a->size;
+ }
+@@ -1253,6 +1256,8 @@ static int do_file(char const *const fna
+ #ifdef MCOUNT_SORT_ENABLED
+               sort_reloc = true;
+               rela_type = 0x403;
++              /* arm64 uses patchable function entry placing before function */
++              before_func = 8;
+ #endif
+               /* fallthrough */
+       case EM_386:
diff --git a/queue-6.12/scripts-sorttable-always-use-an-array-for-the-mcount_loc-sorting.patch b/queue-6.12/scripts-sorttable-always-use-an-array-for-the-mcount_loc-sorting.patch
new file mode 100644 (file)
index 0000000..ec18307
--- /dev/null
@@ -0,0 +1,235 @@
+From stable+bounces-267218-greg=kroah.com@vger.kernel.org Thu Jun 18 21:16:52 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:32 -0400
+Subject: scripts/sorttable: Always use an array for the mcount_loc sorting
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <64aae6881f5521a50e49dd5bf896da200f28a8d4.1781809963.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 5fb964f5ba53afda0e2b6dbc00b8205461ffe04a ]
+
+The sorting of the mcount_loc section is done directly to the section for
+x86 and arm32 but it uses a separate array for arm64 as arm64 has the
+values for the mcount_loc stored in the rela sections of the vmlinux ELF
+file.
+
+In order to use the same code to remove weak functions, always use a
+separate array to do the sorting. This requires splitting up the filling
+of the array into one function and the placing the contents of the array
+back into the rela sections or into the mcount_loc section into a separate
+file.
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Heiko Carstens <hca@linux.ibm.com>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: Vasily Gorbik <gor@linux.ibm.com>
+Cc: Alexander Gordeev <agordeev@linux.ibm.com>
+Link: https://lore.kernel.org/20250218200022.710676551@goodmis.org
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.c |  122 ++++++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 90 insertions(+), 32 deletions(-)
+
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -594,31 +594,19 @@ struct elf_mcount_loc {
+       uint64_t stop_mcount_loc;
+ };
+-/* Sort the relocations not the address itself */
+-static void *sort_relocs(Elf_Ehdr *ehdr, uint64_t start_loc, uint64_t size)
++/* Fill the array with the content of the relocs */
++static int fill_relocs(void *ptr, uint64_t size, Elf_Ehdr *ehdr, uint64_t start_loc)
+ {
+       Elf_Shdr *shdr_start;
+       Elf_Rela *rel;
+       unsigned int shnum;
+-      unsigned int count;
++      unsigned int count = 0;
+       int shentsize;
+-      void *vals;
+-      void *ptr;
+-
+-      compare_values = long_size == 4 ? compare_values_32 : compare_values_64;
++      void *array_end = ptr + size;
+       shdr_start = (Elf_Shdr *)((char *)ehdr + ehdr_shoff(ehdr));
+       shentsize = ehdr_shentsize(ehdr);
+-      vals = malloc(long_size * size);
+-      if (!vals) {
+-              snprintf(m_err, ERRSTR_MAXSZ, "Failed to allocate sort array");
+-              pthread_exit(m_err);
+-              return NULL;
+-      }
+-
+-      ptr = vals;
+-
+       shnum = ehdr_shnum(ehdr);
+       if (shnum == SHN_UNDEF)
+               shnum = shdr_size(shdr_start);
+@@ -637,22 +625,18 @@ static void *sort_relocs(Elf_Ehdr *ehdr,
+                       uint64_t offset = rela_offset(rel);
+                       if (offset >= start_loc && offset < start_loc + size) {
+-                              if (ptr + long_size > vals + size) {
+-                                      free(vals);
++                              if (ptr + long_size > array_end) {
+                                       snprintf(m_err, ERRSTR_MAXSZ,
+                                                "Too many relocations");
+-                                      pthread_exit(m_err);
+-                                      return NULL;
++                                      return -1;
+                               }
+                               /* Make sure this has the correct type */
+                               if (rela_info(rel) != rela_type) {
+-                                      free(vals);
+                                       snprintf(m_err, ERRSTR_MAXSZ,
+                                               "rela has type %lx but expected %lx\n",
+                                               (long)rela_info(rel), rela_type);
+-                                      pthread_exit(m_err);
+-                                      return NULL;
++                                      return -1;
+                               }
+                               if (long_size == 4)
+@@ -660,13 +644,28 @@ static void *sort_relocs(Elf_Ehdr *ehdr,
+                               else
+                                       *(uint64_t *)ptr = rela_addend(rel);
+                               ptr += long_size;
++                              count++;
+                       }
+               }
+       }
+-      count = ptr - vals;
+-      qsort(vals, count / long_size, long_size, compare_values);
++      return count;
++}
++
++/* Put the sorted vals back into the relocation elements */
++static void replace_relocs(void *ptr, uint64_t size, Elf_Ehdr *ehdr, uint64_t start_loc)
++{
++      Elf_Shdr *shdr_start;
++      Elf_Rela *rel;
++      unsigned int shnum;
++      int shentsize;
++
++      shdr_start = (Elf_Shdr *)((char *)ehdr + ehdr_shoff(ehdr));
++      shentsize = ehdr_shentsize(ehdr);
++
++      shnum = ehdr_shnum(ehdr);
++      if (shnum == SHN_UNDEF)
++              shnum = shdr_size(shdr_start);
+-      ptr = vals;
+       for (int i = 0; i < shnum; i++) {
+               Elf_Shdr *shdr = get_index(shdr_start, shentsize, i);
+               void *end;
+@@ -689,8 +688,32 @@ static void *sort_relocs(Elf_Ehdr *ehdr,
+                       }
+               }
+       }
+-      free(vals);
+-      return NULL;
++}
++
++static int fill_addrs(void *ptr, uint64_t size, void *addrs)
++{
++      void *end = ptr + size;
++      int count = 0;
++
++      for (; ptr < end; ptr += long_size, addrs += long_size, count++) {
++              if (long_size == 4)
++                      *(uint32_t *)ptr = r(addrs);
++              else
++                      *(uint64_t *)ptr = r8(addrs);
++      }
++      return count;
++}
++
++static void replace_addrs(void *ptr, uint64_t size, void *addrs)
++{
++      void *end = ptr + size;
++
++      for (; ptr < end; ptr += long_size, addrs += long_size) {
++              if (long_size == 4)
++                      w(*(uint32_t *)ptr, addrs);
++              else
++                      w8(*(uint64_t *)ptr, addrs);
++      }
+ }
+ /* Sort the addresses stored between __start_mcount_loc to __stop_mcount_loc in vmlinux */
+@@ -699,14 +722,49 @@ static void *sort_mcount_loc(void *arg)
+       struct elf_mcount_loc *emloc = (struct elf_mcount_loc *)arg;
+       uint64_t offset = emloc->start_mcount_loc - shdr_addr(emloc->init_data_sec)
+                                       + shdr_offset(emloc->init_data_sec);
+-      uint64_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc;
++      uint64_t size = emloc->stop_mcount_loc - emloc->start_mcount_loc;
+       unsigned char *start_loc = (void *)emloc->ehdr + offset;
++      Elf_Ehdr *ehdr = emloc->ehdr;
++      void *e_msg = NULL;
++      void *vals;
++      int count;
++
++      vals = malloc(long_size * size);
++      if (!vals) {
++              snprintf(m_err, ERRSTR_MAXSZ, "Failed to allocate sort array");
++              pthread_exit(m_err);
++      }
+       if (sort_reloc)
+-              return sort_relocs(emloc->ehdr, emloc->start_mcount_loc, count);
++              count = fill_relocs(vals, size, ehdr, emloc->start_mcount_loc);
++      else
++              count = fill_addrs(vals, size, start_loc);
++
++      if (count < 0) {
++              e_msg = m_err;
++              goto out;
++      }
++
++      if (count != size / long_size) {
++              snprintf(m_err, ERRSTR_MAXSZ, "Expected %u mcount elements but found %u\n",
++                      (int)(size / long_size), count);
++              e_msg = m_err;
++              goto out;
++      }
++
++      compare_values = long_size == 4 ? compare_values_32 : compare_values_64;
++
++      qsort(vals, count, long_size, compare_values);
++
++      if (sort_reloc)
++              replace_relocs(vals, size, ehdr, emloc->start_mcount_loc);
++      else
++              replace_addrs(vals, size, start_loc);
++
++out:
++      free(vals);
+-      qsort(start_loc, count/long_size, long_size, compare_extable);
+-      return NULL;
++      pthread_exit(e_msg);
+ }
+ /* Get the address of __start_mcount_loc and __stop_mcount_loc in System.map */
diff --git a/queue-6.12/scripts-sorttable-convert-elf_ehdr-to-union.patch b/queue-6.12/scripts-sorttable-convert-elf_ehdr-to-union.patch
new file mode 100644 (file)
index 0000000..a291e52
--- /dev/null
@@ -0,0 +1,208 @@
+From prvs=262951c835=andrey.grodzovsky@crowdstrike.com Thu Jun 18 21:16:03 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:20 -0400
+Subject: scripts/sorttable: Convert Elf_Ehdr to union
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <ffbf4890fa9bdef1135c98294fc40bbe5f918004.1781809926.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 157fb5b3cfd2cb5950314f926a76e567fc1921c5 ]
+
+In order to remove the double #include of sorttable.h for 64 and 32 bit
+to create duplicate functions for both, replace the Elf_Ehdr macro with a
+union that defines both Elf64_Ehdr and Elf32_Ehdr, with field e64 for the
+64bit version, and e32 for the 32bit version.
+
+Then a macro etype can be used instead to get to the proper value.
+
+This will eventually be replaced with just single functions that can
+handle both 32bit and 64bit ELF parsing.
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Link: https://lore.kernel.org/20250105162345.148224465@goodmis.org
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.c |   36 ++++++++++++++++++++----------------
+ scripts/sorttable.h |   12 ++++++------
+ 2 files changed, 26 insertions(+), 22 deletions(-)
+
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -64,6 +64,11 @@
+ #define EM_LOONGARCH  258
+ #endif
++typedef union {
++      Elf32_Ehdr      e32;
++      Elf64_Ehdr      e64;
++} Elf_Ehdr;
++
+ static uint32_t (*r)(const uint32_t *);
+ static uint16_t (*r2)(const uint16_t *);
+ static uint64_t (*r8)(const uint64_t *);
+@@ -266,10 +271,10 @@ static void sort_relative_table_with_dat
+ static int do_file(char const *const fname, void *addr)
+ {
+       int rc = -1;
+-      Elf32_Ehdr *ehdr = addr;
++      Elf_Ehdr *ehdr = addr;
+       table_sort_t custom_sort = NULL;
+-      switch (ehdr->e_ident[EI_DATA]) {
++      switch (ehdr->e32.e_ident[EI_DATA]) {
+       case ELFDATA2LSB:
+               r       = rle;
+               r2      = r2le;
+@@ -284,18 +289,18 @@ static int do_file(char const *const fna
+               break;
+       default:
+               fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
+-                      ehdr->e_ident[EI_DATA], fname);
++                      ehdr->e32.e_ident[EI_DATA], fname);
+               return -1;
+       }
+-      if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 ||
+-          (r2(&ehdr->e_type) != ET_EXEC && r2(&ehdr->e_type) != ET_DYN) ||
+-          ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
++      if (memcmp(ELFMAG, ehdr->e32.e_ident, SELFMAG) != 0 ||
++          (r2(&ehdr->e32.e_type) != ET_EXEC && r2(&ehdr->e32.e_type) != ET_DYN) ||
++          ehdr->e32.e_ident[EI_VERSION] != EV_CURRENT) {
+               fprintf(stderr, "unrecognized ET_EXEC/ET_DYN file %s\n", fname);
+               return -1;
+       }
+-      switch (r2(&ehdr->e_machine)) {
++      switch (r2(&ehdr->e32.e_machine)) {
+       case EM_386:
+       case EM_AARCH64:
+       case EM_LOONGARCH:
+@@ -318,14 +323,14 @@ static int do_file(char const *const fna
+               break;
+       default:
+               fprintf(stderr, "unrecognized e_machine %d %s\n",
+-                      r2(&ehdr->e_machine), fname);
++                      r2(&ehdr->e32.e_machine), fname);
+               return -1;
+       }
+-      switch (ehdr->e_ident[EI_CLASS]) {
++      switch (ehdr->e32.e_ident[EI_CLASS]) {
+       case ELFCLASS32:
+-              if (r2(&ehdr->e_ehsize) != sizeof(Elf32_Ehdr) ||
+-                  r2(&ehdr->e_shentsize) != sizeof(Elf32_Shdr)) {
++              if (r2(&ehdr->e32.e_ehsize) != sizeof(Elf32_Ehdr) ||
++                  r2(&ehdr->e32.e_shentsize) != sizeof(Elf32_Shdr)) {
+                       fprintf(stderr,
+                               "unrecognized ET_EXEC/ET_DYN file: %s\n", fname);
+                       break;
+@@ -334,20 +339,19 @@ static int do_file(char const *const fna
+               break;
+       case ELFCLASS64:
+               {
+-              Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr;
+-              if (r2(&ghdr->e_ehsize) != sizeof(Elf64_Ehdr) ||
+-                  r2(&ghdr->e_shentsize) != sizeof(Elf64_Shdr)) {
++              if (r2(&ehdr->e64.e_ehsize) != sizeof(Elf64_Ehdr) ||
++                  r2(&ehdr->e64.e_shentsize) != sizeof(Elf64_Shdr)) {
+                       fprintf(stderr,
+                               "unrecognized ET_EXEC/ET_DYN file: %s\n",
+                               fname);
+                       break;
+               }
+-              rc = do_sort_64(ghdr, fname, custom_sort);
++              rc = do_sort_64(ehdr, fname, custom_sort);
+               }
+               break;
+       default:
+               fprintf(stderr, "unrecognized ELF class %d %s\n",
+-                      ehdr->e_ident[EI_CLASS], fname);
++                      ehdr->e32.e_ident[EI_CLASS], fname);
+               break;
+       }
+--- a/scripts/sorttable.h
++++ b/scripts/sorttable.h
+@@ -23,12 +23,12 @@
+ #undef sort_mcount_loc
+ #undef elf_mcount_loc
+ #undef do_sort
+-#undef Elf_Ehdr
+ #undef Elf_Shdr
+ #undef Elf_Sym
+ #undef ELF_ST_TYPE
+ #undef uint_t
+ #undef _r
++#undef etype
+ #ifdef SORTTABLE_64
+ # define extable_ent_size     16
+@@ -37,12 +37,12 @@
+ # define sort_mcount_loc      sort_mcount_loc_64
+ # define elf_mcount_loc               elf_mcount_loc_64
+ # define do_sort              do_sort_64
+-# define Elf_Ehdr             Elf64_Ehdr
+ # define Elf_Shdr             Elf64_Shdr
+ # define Elf_Sym              Elf64_Sym
+ # define ELF_ST_TYPE          ELF64_ST_TYPE
+ # define uint_t                       uint64_t
+ # define _r                   r8
++# define etype                        e64
+ #else
+ # define extable_ent_size     8
+ # define compare_extable      compare_extable_32
+@@ -50,12 +50,12 @@
+ # define sort_mcount_loc      sort_mcount_loc_32
+ # define elf_mcount_loc               elf_mcount_loc_32
+ # define do_sort              do_sort_32
+-# define Elf_Ehdr             Elf32_Ehdr
+ # define Elf_Shdr             Elf32_Shdr
+ # define Elf_Sym              Elf32_Sym
+ # define ELF_ST_TYPE          ELF32_ST_TYPE
+ # define uint_t                       uint32_t
+ # define _r                   r
++# define etype                        e32
+ #endif
+ #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+@@ -222,7 +222,7 @@ static int do_sort(Elf_Ehdr *ehdr,
+                  table_sort_t custom_sort)
+ {
+       int rc = -1;
+-      Elf_Shdr *s, *shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->e_shoff));
++      Elf_Shdr *s, *shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->etype.e_shoff));
+       Elf_Shdr *strtab_sec = NULL;
+       Elf_Shdr *symtab_sec = NULL;
+       Elf_Shdr *extab_sec = NULL;
+@@ -249,12 +249,12 @@ static int do_sort(Elf_Ehdr *ehdr,
+       unsigned int orc_num_entries = 0;
+ #endif
+-      shstrndx = r2(&ehdr->e_shstrndx);
++      shstrndx = r2(&ehdr->etype.e_shstrndx);
+       if (shstrndx == SHN_XINDEX)
+               shstrndx = r(&shdr[0].sh_link);
+       secstrings = (const char *)ehdr + _r(&shdr[shstrndx].sh_offset);
+-      shnum = r2(&ehdr->e_shnum);
++      shnum = r2(&ehdr->etype.e_shnum);
+       if (shnum == SHN_UNDEF)
+               shnum = _r(&shdr[0].sh_size);
diff --git a/queue-6.12/scripts-sorttable-convert-elf_sym-macro-over-to-a-union.patch b/queue-6.12/scripts-sorttable-convert-elf_sym-macro-over-to-a-union.patch
new file mode 100644 (file)
index 0000000..622c30f
--- /dev/null
@@ -0,0 +1,137 @@
+From prvs=262951c835=andrey.grodzovsky@crowdstrike.com Thu Jun 18 21:16:00 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:22 -0400
+Subject: scripts/sorttable: Convert Elf_Sym MACRO over to a union
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <730403c91a917d659d9dfbf21ba9a57959ef1051.1781809932.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 200d015e73b4da69bcd8212a7c58695452b12bad ]
+
+In order to remove the double #include of sorttable.h for 64 and 32 bit
+to create duplicate functions for both, replace the Elf_Sym macro with a
+union that defines both Elf64_Sym and Elf32_Sym, with field e64 for the
+64bit version, and e32 for the 32bit version.
+
+It can then use the macro etype to get the proper value.
+
+This will eventually be replaced with just single functions that can
+handle both 32bit and 64bit ELF parsing.
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Link: https://lore.kernel.org/20250105162345.528626969@goodmis.org
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.c |    5 +++++
+ scripts/sorttable.h |   25 ++++++++++++++-----------
+ 2 files changed, 19 insertions(+), 11 deletions(-)
+
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -74,6 +74,11 @@ typedef union {
+       Elf64_Shdr      e64;
+ } Elf_Shdr;
++typedef union {
++      Elf32_Sym       e32;
++      Elf64_Sym       e64;
++} Elf_Sym;
++
+ static uint32_t (*r)(const uint32_t *);
+ static uint16_t (*r2)(const uint16_t *);
+ static uint64_t (*r8)(const uint64_t *);
+--- a/scripts/sorttable.h
++++ b/scripts/sorttable.h
+@@ -23,7 +23,6 @@
+ #undef sort_mcount_loc
+ #undef elf_mcount_loc
+ #undef do_sort
+-#undef Elf_Sym
+ #undef ELF_ST_TYPE
+ #undef uint_t
+ #undef _r
+@@ -36,7 +35,6 @@
+ # define sort_mcount_loc      sort_mcount_loc_64
+ # define elf_mcount_loc               elf_mcount_loc_64
+ # define do_sort              do_sort_64
+-# define Elf_Sym              Elf64_Sym
+ # define ELF_ST_TYPE          ELF64_ST_TYPE
+ # define uint_t                       uint64_t
+ # define _r                   r8
+@@ -48,7 +46,6 @@
+ # define sort_mcount_loc      sort_mcount_loc_32
+ # define elf_mcount_loc               elf_mcount_loc_32
+ # define do_sort              do_sort_32
+-# define Elf_Sym              Elf32_Sym
+ # define ELF_ST_TYPE          ELF32_ST_TYPE
+ # define uint_t                       uint32_t
+ # define _r                   r
+@@ -230,10 +227,13 @@ static int do_sort(Elf_Ehdr *ehdr,
+       Elf_Sym *sort_needed_sym = NULL;
+       Elf_Shdr *sort_needed_sec;
+       uint32_t *sort_needed_loc;
++      void *sym_start;
++      void *sym_end;
+       const char *secstrings;
+       const char *strtab;
+       char *extab_image;
+       int sort_need_index;
++      int symentsize;
+       int shentsize;
+       int idx;
+       int i;
+@@ -376,12 +376,15 @@ static int do_sort(Elf_Ehdr *ehdr,
+       }
+       /* find the flag main_extable_sort_needed */
+-      for (sym = (void *)ehdr + _r(&symtab_sec->etype.sh_offset);
+-           sym < sym + _r(&symtab_sec->etype.sh_size) / sizeof(Elf_Sym);
+-           sym++) {
+-              if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
++      sym_start = (void *)ehdr + _r(&symtab_sec->etype.sh_offset);
++      sym_end = sym_start + _r(&symtab_sec->etype.sh_size);
++      symentsize = _r(&symtab_sec->etype.sh_entsize);
++
++      for (sym = sym_start; (void *)sym + symentsize < sym_end;
++           sym = (void *)sym + symentsize) {
++              if (ELF_ST_TYPE(sym->etype.st_info) != STT_OBJECT)
+                       continue;
+-              if (!strcmp(strtab + r(&sym->st_name),
++              if (!strcmp(strtab + r(&sym->etype.st_name),
+                           "main_extable_sort_needed")) {
+                       sort_needed_sym = sym;
+                       break;
+@@ -395,13 +398,13 @@ static int do_sort(Elf_Ehdr *ehdr,
+               goto out;
+       }
+-      sort_need_index = get_secindex(r2(&sym->st_shndx),
+-                                     sort_needed_sym - symtab,
++      sort_need_index = get_secindex(r2(&sym->etype.st_shndx),
++                                     ((void *)sort_needed_sym - (void *)symtab) / symentsize,
+                                      symtab_shndx);
+       sort_needed_sec = get_index(shdr_start, shentsize, sort_need_index);
+       sort_needed_loc = (void *)ehdr +
+               _r(&sort_needed_sec->etype.sh_offset) +
+-              _r(&sort_needed_sym->st_value) -
++              _r(&sort_needed_sym->etype.st_value) -
+               _r(&sort_needed_sec->etype.sh_addr);
+       /* extable has been sorted, clear the flag */
diff --git a/queue-6.12/scripts-sorttable-fix-endianness-handling-in-build-time-mcount-sort.patch b/queue-6.12/scripts-sorttable-fix-endianness-handling-in-build-time-mcount-sort.patch
new file mode 100644 (file)
index 0000000..969bda9
--- /dev/null
@@ -0,0 +1,51 @@
+From stable+bounces-267227-greg=kroah.com@vger.kernel.org Thu Jun 18 21:17:57 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:41 -0400
+Subject: scripts/sorttable: Fix endianness handling in build-time mcount sort
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <260290837178d984dbf07c74176f8997b62b42d8.1781809990.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Vasily Gorbik <gor@linux.ibm.com>
+
+[ Upstream commit 023f124a64174c47e18340ded7e2a39b96eb9523 ]
+
+Kernel cross-compilation with BUILDTIME_MCOUNT_SORT produces zeroed
+mcount values if the build-host endianness does not match the ELF
+file endianness.
+
+The mcount values array is converted from ELF file
+endianness to build-host endianness during initialization in
+fill_relocs()/fill_addrs(). Avoid extra conversion of these values during
+weak-function zeroing; otherwise, they do not match nm-parsed addresses
+and all mcount values are zeroed out.
+
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Heiko Carstens <hca@linux.ibm.com>
+Cc: Alexander Gordeev <agordeev@linux.ibm.com>
+Link: https://lore.kernel.org/patch.git-dca31444b0f1.your-ad-here.call-01743554658-ext-8692@work.hours
+Fixes: ef378c3b8233 ("scripts/sorttable: Zero out weak functions in mcount_loc table")
+Reported-by: Ilya Leoshkevich <iii@linux.ibm.com>
+Reported-by: Ihor Solodrai <ihor.solodrai@linux.dev>
+Closes: https://lore.kernel.org/all/your-ad-here.call-01743522822-ext-4975@work.hours/
+Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -857,7 +857,7 @@ static void *sort_mcount_loc(void *arg)
+               for (void *ptr = vals; ptr < vals + size; ptr += long_size) {
+                       uint64_t key;
+-                      key = long_size == 4 ? r((uint32_t *)ptr) : r8((uint64_t *)ptr);
++                      key = long_size == 4 ? *(uint32_t *)ptr : *(uint64_t *)ptr;
+                       if (!find_func(key)) {
+                               if (long_size == 4)
+                                       *(uint32_t *)ptr = 0;
diff --git a/queue-6.12/scripts-sorttable-get-start-stop_mcount_loc-from-elf-file-directly.patch b/queue-6.12/scripts-sorttable-get-start-stop_mcount_loc-from-elf-file-directly.patch
new file mode 100644 (file)
index 0000000..92be050
--- /dev/null
@@ -0,0 +1,192 @@
+From stable+bounces-267213-greg=kroah.com@vger.kernel.org Thu Jun 18 21:16:18 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:28 -0400
+Subject: scripts/sorttable: Get start/stop_mcount_loc from ELF file directly
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <1f651dfe741838b94ed8088cc3429b65768893ea.1781809952.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 4acda8edefa1ce66d3de845f1c12745721cd14c3 ]
+
+The get_mcount_loc() does a cheesy trick to find the start_mcount_loc and
+stop_mcount_loc values. That trick is:
+
+ file_start = popen(" grep start_mcount System.map | awk '{print $1}' ", "r");
+
+and
+
+ file_stop = popen(" grep stop_mcount System.map | awk '{print $1}' ", "r");
+
+Those values are stored in the Elf symbol table. Use that to capture those
+values. Using the symbol table is more efficient and more robust. The
+above could fail if another variable had "start_mcount" or "stop_mcount"
+as part of its name.
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Link: https://lore.kernel.org/20250105162346.817157047@goodmis.org
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.c |   95 ++++++++++++++++++++++++----------------------------
+ 1 file changed, 45 insertions(+), 50 deletions(-)
+
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -472,42 +472,41 @@ static void *sort_mcount_loc(void *arg)
+ }
+ /* Get the address of __start_mcount_loc and __stop_mcount_loc in System.map */
+-static void get_mcount_loc(uint64_t *_start, uint64_t *_stop)
++static void get_mcount_loc(struct elf_mcount_loc *emloc, Elf_Shdr *symtab_sec,
++                         const char *strtab)
+ {
+-      FILE *file_start, *file_stop;
+-      char start_buff[20];
+-      char stop_buff[20];
+-      int len = 0;
++      Elf_Sym *sym, *end_sym;
++      int symentsize = shdr_entsize(symtab_sec);
++      int found = 0;
++
++      sym = (void *)emloc->ehdr + shdr_offset(symtab_sec);
++      end_sym = (void *)sym + shdr_size(symtab_sec);
++
++      while (sym < end_sym) {
++              if (!strcmp(strtab + sym_name(sym), "__start_mcount_loc")) {
++                      emloc->start_mcount_loc = sym_value(sym);
++                      if (++found == 2)
++                              break;
++              } else if (!strcmp(strtab + sym_name(sym), "__stop_mcount_loc")) {
++                      emloc->stop_mcount_loc = sym_value(sym);
++                      if (++found == 2)
++                              break;
++              }
++              sym = (void *)sym + symentsize;
++      }
+-      file_start = popen(" grep start_mcount System.map | awk '{print $1}' ", "r");
+-      if (!file_start) {
++      if (!emloc->start_mcount_loc) {
+               fprintf(stderr, "get start_mcount_loc error!");
+               return;
+       }
+-      file_stop = popen(" grep stop_mcount System.map | awk '{print $1}' ", "r");
+-      if (!file_stop) {
++      if (!emloc->stop_mcount_loc) {
+               fprintf(stderr, "get stop_mcount_loc error!");
+-              pclose(file_start);
+               return;
+       }
+-
+-      while (fgets(start_buff, sizeof(start_buff), file_start) != NULL) {
+-              len = strlen(start_buff);
+-              start_buff[len - 1] = '\0';
+-      }
+-      *_start = strtoul(start_buff, NULL, 16);
+-
+-      while (fgets(stop_buff, sizeof(stop_buff), file_stop) != NULL) {
+-              len = strlen(stop_buff);
+-              stop_buff[len - 1] = '\0';
+-      }
+-      *_stop = strtoul(stop_buff, NULL, 16);
+-
+-      pclose(file_start);
+-      pclose(file_stop);
+ }
+ #endif
++
+ static int do_sort(Elf_Ehdr *ehdr,
+                  char const *const fname,
+                  table_sort_t custom_sort)
+@@ -538,8 +537,6 @@ static int do_sort(Elf_Ehdr *ehdr,
+       unsigned int shstrndx;
+ #ifdef MCOUNT_SORT_ENABLED
+       struct elf_mcount_loc mstruct = {0};
+-      uint64_t _start_mcount_loc = 0;
+-      uint64_t _stop_mcount_loc = 0;
+ #endif
+ #ifdef UNWINDER_ORC_ENABLED
+       unsigned int orc_ip_size = 0;
+@@ -577,13 +574,8 @@ static int do_sort(Elf_Ehdr *ehdr,
+ #ifdef MCOUNT_SORT_ENABLED
+               /* locate the .init.data section in vmlinux */
+-              if (!strcmp(secstrings + idx, ".init.data")) {
+-                      get_mcount_loc(&_start_mcount_loc, &_stop_mcount_loc);
+-                      mstruct.ehdr = ehdr;
++              if (!strcmp(secstrings + idx, ".init.data"))
+                       mstruct.init_data_sec = shdr;
+-                      mstruct.start_mcount_loc = _start_mcount_loc;
+-                      mstruct.stop_mcount_loc = _stop_mcount_loc;
+-              }
+ #endif
+ #ifdef UNWINDER_ORC_ENABLED
+@@ -627,23 +619,6 @@ static int do_sort(Elf_Ehdr *ehdr,
+               goto out;
+       }
+ #endif
+-
+-#ifdef MCOUNT_SORT_ENABLED
+-      if (!mstruct.init_data_sec || !_start_mcount_loc || !_stop_mcount_loc) {
+-              fprintf(stderr,
+-                      "incomplete mcount's sort in file: %s\n",
+-                      fname);
+-              goto out;
+-      }
+-
+-      /* create thread to sort mcount_loc concurrently */
+-      if (pthread_create(&mcount_sort_thread, NULL, &sort_mcount_loc, &mstruct)) {
+-              fprintf(stderr,
+-                      "pthread_create mcount_sort_thread failed '%s': %s\n",
+-                      strerror(errno), fname);
+-              goto out;
+-      }
+-#endif
+       if (!extab_sec) {
+               fprintf(stderr, "no __ex_table in file: %s\n", fname);
+               goto out;
+@@ -663,6 +638,26 @@ static int do_sort(Elf_Ehdr *ehdr,
+       strtab = (const char *)ehdr + shdr_offset(strtab_sec);
+       symtab = (const Elf_Sym *)((const char *)ehdr + shdr_offset(symtab_sec));
++#ifdef MCOUNT_SORT_ENABLED
++      mstruct.ehdr = ehdr;
++      get_mcount_loc(&mstruct, symtab_sec, strtab);
++
++      if (!mstruct.init_data_sec || !mstruct.start_mcount_loc || !mstruct.stop_mcount_loc) {
++              fprintf(stderr,
++                      "incomplete mcount's sort in file: %s\n",
++                      fname);
++              goto out;
++      }
++
++      /* create thread to sort mcount_loc concurrently */
++      if (pthread_create(&mcount_sort_thread, NULL, &sort_mcount_loc, &mstruct)) {
++              fprintf(stderr,
++                      "pthread_create mcount_sort_thread failed '%s': %s\n",
++                      strerror(errno), fname);
++              goto out;
++      }
++#endif
++
+       if (custom_sort) {
+               custom_sort(extab_image, shdr_size(extab_sec));
+       } else {
diff --git a/queue-6.12/scripts-sorttable-have-mcount-rela-sort-use-direct-values.patch b/queue-6.12/scripts-sorttable-have-mcount-rela-sort-use-direct-values.patch
new file mode 100644 (file)
index 0000000..96b34e5
--- /dev/null
@@ -0,0 +1,100 @@
+From stable+bounces-267217-greg=kroah.com@vger.kernel.org Thu Jun 18 21:16:18 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:31 -0400
+Subject: scripts/sorttable: Have mcount rela sort use direct values
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <08a39ed51d7a5c5b62f0ddf7e54f99e955ec0b15.1781809961.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit a0265659322540d656727b9e132edfb6f06b6c1a ]
+
+The mcount_loc sorting for when the values are stored in the Elf_Rela
+entries uses the compare_extable() function to do the compares in the
+qsort(). That function does handle byte swapping if the machine being
+compiled for is a different endian than the host machine. But the
+sort_relocs() function sorts an array that pulled in the values from the
+Elf_Rela section and has already done the swapping.
+
+Create two new compare functions that will sort the direct values. One
+will sort 32 bit values and the other will sort the 64 bit value. One of
+these will be assigned to a compare_values function pointer and that will
+be used for sorting the Elf_Rela mcount values.
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Heiko Carstens <hca@linux.ibm.com>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: Vasily Gorbik <gor@linux.ibm.com>
+Cc: Alexander Gordeev <agordeev@linux.ibm.com>
+Link: https://lore.kernel.org/20250218200022.538888594@goodmis.org
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.c |   26 +++++++++++++++++++++++++-
+ 1 file changed, 25 insertions(+), 1 deletion(-)
+
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -552,6 +552,28 @@ static void *sort_orctable(void *arg)
+ #ifdef MCOUNT_SORT_ENABLED
++static int compare_values_64(const void *a, const void *b)
++{
++      uint64_t av = *(uint64_t *)a;
++      uint64_t bv = *(uint64_t *)b;
++
++      if (av < bv)
++              return -1;
++      return av > bv;
++}
++
++static int compare_values_32(const void *a, const void *b)
++{
++      uint32_t av = *(uint32_t *)a;
++      uint32_t bv = *(uint32_t *)b;
++
++      if (av < bv)
++              return -1;
++      return av > bv;
++}
++
++static int (*compare_values)(const void *a, const void *b);
++
+ /* Only used for sorting mcount table */
+ static void rela_write_addend(Elf_Rela *rela, uint64_t val)
+ {
+@@ -583,6 +605,8 @@ static void *sort_relocs(Elf_Ehdr *ehdr,
+       void *vals;
+       void *ptr;
++      compare_values = long_size == 4 ? compare_values_32 : compare_values_64;
++
+       shdr_start = (Elf_Shdr *)((char *)ehdr + ehdr_shoff(ehdr));
+       shentsize = ehdr_shentsize(ehdr);
+@@ -640,7 +664,7 @@ static void *sort_relocs(Elf_Ehdr *ehdr,
+               }
+       }
+       count = ptr - vals;
+-      qsort(vals, count / long_size, long_size, compare_extable);
++      qsort(vals, count / long_size, long_size, compare_values);
+       ptr = vals;
+       for (int i = 0; i < shnum; i++) {
diff --git a/queue-6.12/scripts-sorttable-have-the-orc-code-use-the-_r-functions-to-read.patch b/queue-6.12/scripts-sorttable-have-the-orc-code-use-the-_r-functions-to-read.patch
new file mode 100644 (file)
index 0000000..bba638e
--- /dev/null
@@ -0,0 +1,61 @@
+From prvs=262951c835=andrey.grodzovsky@crowdstrike.com Thu Jun 18 21:16:01 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:18 -0400
+Subject: scripts/sorttable: Have the ORC code use the _r() functions to read
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <8192a8bd228bb0d727a7c048b2ec034f9e9ccc8b.1781809920.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 66990c003306c240d570b3ba274ec4f68cf18c91 ]
+
+The ORC code reads the section information directly from the file. This
+currently works because the default read function is for 64bit little
+endian machines. But if for some reason that ever changes, this will
+break. Instead of having a surprise breakage, use the _r() functions that
+will read the values from the file properly.
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Link: https://lore.kernel.org/20250105162344.721480386@goodmis.org
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.h |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/scripts/sorttable.h
++++ b/scripts/sorttable.h
+@@ -299,14 +299,14 @@ static int do_sort(Elf_Ehdr *ehdr,
+ #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+               /* locate the ORC unwind tables */
+               if (!strcmp(secstrings + idx, ".orc_unwind_ip")) {
+-                      orc_ip_size = s->sh_size;
++                      orc_ip_size = _r(&s->sh_size);
+                       g_orc_ip_table = (int *)((void *)ehdr +
+-                                                 s->sh_offset);
++                                                 _r(&s->sh_offset));
+               }
+               if (!strcmp(secstrings + idx, ".orc_unwind")) {
+-                      orc_size = s->sh_size;
++                      orc_size = _r(&s->sh_size);
+                       g_orc_table = (struct orc_entry *)((void *)ehdr +
+-                                                           s->sh_offset);
++                                                           _r(&s->sh_offset));
+               }
+ #endif
+       } /* for loop */
diff --git a/queue-6.12/scripts-sorttable-make-compare_extable-into-two-functions.patch b/queue-6.12/scripts-sorttable-make-compare_extable-into-two-functions.patch
new file mode 100644 (file)
index 0000000..ff539b9
--- /dev/null
@@ -0,0 +1,128 @@
+From stable+bounces-267209-greg=kroah.com@vger.kernel.org Thu Jun 18 21:16:04 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:19 -0400
+Subject: scripts/sorttable: Make compare_extable() into two functions
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <355a7e43ce293504ed0abde5792b981a7c317d51.1781809922.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 7ffc0d0819f438779ed592e2e2e3576f43ce14f0 ]
+
+Instead of having the compare_extable() part of the sorttable.h header
+where it get's defined twice, since it is a very simple function, just
+define it twice in sorttable.c, and then it can use the proper read
+functions for the word size and endianess and the Elf_Addr macro can be
+removed from sorttable.h.
+
+Also add a micro optimization. Instead of:
+
+    if (a < b)
+        return -1;
+    if (a > b)
+        return 1;
+    return 0;
+
+That can be shorten to:
+
+   if (a < b)
+      return -1;
+   return a > b;
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Link: https://lore.kernel.org/20250105162344.945299671@goodmis.org
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.c |   20 ++++++++++++++++++++
+ scripts/sorttable.h |   14 --------------
+ 2 files changed, 20 insertions(+), 14 deletions(-)
+
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -173,6 +173,26 @@ static inline unsigned int get_secindex(
+       return r(&symtab_shndx_start[sym_offs]);
+ }
++static int compare_extable_32(const void *a, const void *b)
++{
++      Elf32_Addr av = r(a);
++      Elf32_Addr bv = r(b);
++
++      if (av < bv)
++              return -1;
++      return av > bv;
++}
++
++static int compare_extable_64(const void *a, const void *b)
++{
++      Elf64_Addr av = r8(a);
++      Elf64_Addr bv = r8(b);
++
++      if (av < bv)
++              return -1;
++      return av > bv;
++}
++
+ /* 32 bit and 64 bit are very similar */
+ #include "sorttable.h"
+ #define SORTTABLE_64
+--- a/scripts/sorttable.h
++++ b/scripts/sorttable.h
+@@ -23,7 +23,6 @@
+ #undef sort_mcount_loc
+ #undef elf_mcount_loc
+ #undef do_sort
+-#undef Elf_Addr
+ #undef Elf_Ehdr
+ #undef Elf_Shdr
+ #undef Elf_Sym
+@@ -38,7 +37,6 @@
+ # define sort_mcount_loc      sort_mcount_loc_64
+ # define elf_mcount_loc               elf_mcount_loc_64
+ # define do_sort              do_sort_64
+-# define Elf_Addr             Elf64_Addr
+ # define Elf_Ehdr             Elf64_Ehdr
+ # define Elf_Shdr             Elf64_Shdr
+ # define Elf_Sym              Elf64_Sym
+@@ -52,7 +50,6 @@
+ # define sort_mcount_loc      sort_mcount_loc_32
+ # define elf_mcount_loc               elf_mcount_loc_32
+ # define do_sort              do_sort_32
+-# define Elf_Addr             Elf32_Addr
+ # define Elf_Ehdr             Elf32_Ehdr
+ # define Elf_Shdr             Elf32_Shdr
+ # define Elf_Sym              Elf32_Sym
+@@ -160,17 +157,6 @@ static void *sort_orctable(void *arg)
+ }
+ #endif
+-static int compare_extable(const void *a, const void *b)
+-{
+-      Elf_Addr av = _r(a);
+-      Elf_Addr bv = _r(b);
+-
+-      if (av < bv)
+-              return -1;
+-      if (av > bv)
+-              return 1;
+-      return 0;
+-}
+ #ifdef MCOUNT_SORT_ENABLED
+ pthread_t mcount_sort_thread;
diff --git a/queue-6.12/scripts-sorttable-move-code-from-sorttable.h-into-sorttable.c.patch b/queue-6.12/scripts-sorttable-move-code-from-sorttable.h-into-sorttable.c.patch
new file mode 100644 (file)
index 0000000..0f06373
--- /dev/null
@@ -0,0 +1,1051 @@
+From stable+bounces-267214-greg=kroah.com@vger.kernel.org Thu Jun 18 21:16:22 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:27 -0400
+Subject: scripts/sorttable: Move code from sorttable.h into sorttable.c
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <6a5629fb83fc0a77348e1ecbf8b31b50b42db27a.1781809949.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 58d87678a0f46c6120904b4326aaf5ebf4454c69 ]
+
+Instead of having the main code live in a header file and included twice
+with MACROs that define the Elf structures for 64 bit or 32 bit, move the
+code in the C file now that the Elf structures are defined in a union that
+has both. All accesses to the Elf structure fields are done through helper
+function pointers. If the file being parsed if for a 64 bit architecture,
+all the helper functions point to the 64 bit versions to retrieve the Elf
+fields. The same is true if the architecture is 32 bit, where the function
+pointers will point to the 32 bit helper functions.
+
+Note, when the value of a field can be either 32 bit or 64 bit, a 64 bit
+is always returned, as it works for the 32 bit code as well.
+
+This makes the code easier to read and maintain, and it now all exists in
+sorttable.c and sorttable.h may be removed.
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Stephen Rothwell <sfr@canb.auug.org.au>
+Link: https://lore.kernel.org/20250107223217.6f7f96a5@gandalf.local.home
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.c |  473 +++++++++++++++++++++++++++++++++++++++++++++++++-
+ scripts/sorttable.h |  485 ----------------------------------------------------
+ 2 files changed, 460 insertions(+), 498 deletions(-)
+ delete mode 100644 scripts/sorttable.h
+
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -327,10 +327,423 @@ static inline void *get_index(void *star
+       return start + (entsize * index);
+ }
+-/* 32 bit and 64 bit are very similar */
+-#include "sorttable.h"
+-#define SORTTABLE_64
+-#include "sorttable.h"
++
++static int (*compare_extable)(const void *a, const void *b);
++static uint64_t (*ehdr_shoff)(Elf_Ehdr *ehdr);
++static uint16_t (*ehdr_shstrndx)(Elf_Ehdr *ehdr);
++static uint16_t (*ehdr_shentsize)(Elf_Ehdr *ehdr);
++static uint16_t (*ehdr_shnum)(Elf_Ehdr *ehdr);
++static uint64_t (*shdr_addr)(Elf_Shdr *shdr);
++static uint64_t (*shdr_offset)(Elf_Shdr *shdr);
++static uint64_t (*shdr_size)(Elf_Shdr *shdr);
++static uint64_t (*shdr_entsize)(Elf_Shdr *shdr);
++static uint32_t (*shdr_link)(Elf_Shdr *shdr);
++static uint32_t (*shdr_name)(Elf_Shdr *shdr);
++static uint32_t (*shdr_type)(Elf_Shdr *shdr);
++static uint8_t (*sym_type)(Elf_Sym *sym);
++static uint32_t (*sym_name)(Elf_Sym *sym);
++static uint64_t (*sym_value)(Elf_Sym *sym);
++static uint16_t (*sym_shndx)(Elf_Sym *sym);
++
++static int extable_ent_size;
++static int long_size;
++
++
++#ifdef UNWINDER_ORC_ENABLED
++/* ORC unwinder only support X86_64 */
++#include <asm/orc_types.h>
++
++#define ERRSTR_MAXSZ  256
++
++static char g_err[ERRSTR_MAXSZ];
++static int *g_orc_ip_table;
++static struct orc_entry *g_orc_table;
++
++static pthread_t orc_sort_thread;
++
++static inline unsigned long orc_ip(const int *ip)
++{
++      return (unsigned long)ip + *ip;
++}
++
++static int orc_sort_cmp(const void *_a, const void *_b)
++{
++      struct orc_entry *orc_a, *orc_b;
++      const int *a = g_orc_ip_table + *(int *)_a;
++      const int *b = g_orc_ip_table + *(int *)_b;
++      unsigned long a_val = orc_ip(a);
++      unsigned long b_val = orc_ip(b);
++
++      if (a_val > b_val)
++              return 1;
++      if (a_val < b_val)
++              return -1;
++
++      /*
++       * The "weak" section terminator entries need to always be on the left
++       * to ensure the lookup code skips them in favor of real entries.
++       * These terminator entries exist to handle any gaps created by
++       * whitelisted .o files which didn't get objtool generation.
++       */
++      orc_a = g_orc_table + (a - g_orc_ip_table);
++      orc_b = g_orc_table + (b - g_orc_ip_table);
++      if (orc_a->type == ORC_TYPE_UNDEFINED && orc_b->type == ORC_TYPE_UNDEFINED)
++              return 0;
++      return orc_a->type == ORC_TYPE_UNDEFINED ? -1 : 1;
++}
++
++static void *sort_orctable(void *arg)
++{
++      int i;
++      int *idxs = NULL;
++      int *tmp_orc_ip_table = NULL;
++      struct orc_entry *tmp_orc_table = NULL;
++      unsigned int *orc_ip_size = (unsigned int *)arg;
++      unsigned int num_entries = *orc_ip_size / sizeof(int);
++      unsigned int orc_size = num_entries * sizeof(struct orc_entry);
++
++      idxs = (int *)malloc(*orc_ip_size);
++      if (!idxs) {
++              snprintf(g_err, ERRSTR_MAXSZ, "malloc idxs: %s",
++                       strerror(errno));
++              pthread_exit(g_err);
++      }
++
++      tmp_orc_ip_table = (int *)malloc(*orc_ip_size);
++      if (!tmp_orc_ip_table) {
++              snprintf(g_err, ERRSTR_MAXSZ, "malloc tmp_orc_ip_table: %s",
++                       strerror(errno));
++              pthread_exit(g_err);
++      }
++
++      tmp_orc_table = (struct orc_entry *)malloc(orc_size);
++      if (!tmp_orc_table) {
++              snprintf(g_err, ERRSTR_MAXSZ, "malloc tmp_orc_table: %s",
++                       strerror(errno));
++              pthread_exit(g_err);
++      }
++
++      /* initialize indices array, convert ip_table to absolute address */
++      for (i = 0; i < num_entries; i++) {
++              idxs[i] = i;
++              tmp_orc_ip_table[i] = g_orc_ip_table[i] + i * sizeof(int);
++      }
++      memcpy(tmp_orc_table, g_orc_table, orc_size);
++
++      qsort(idxs, num_entries, sizeof(int), orc_sort_cmp);
++
++      for (i = 0; i < num_entries; i++) {
++              if (idxs[i] == i)
++                      continue;
++
++              /* convert back to relative address */
++              g_orc_ip_table[i] = tmp_orc_ip_table[idxs[i]] - i * sizeof(int);
++              g_orc_table[i] = tmp_orc_table[idxs[i]];
++      }
++
++      free(idxs);
++      free(tmp_orc_ip_table);
++      free(tmp_orc_table);
++      pthread_exit(NULL);
++}
++#endif
++
++#ifdef MCOUNT_SORT_ENABLED
++static pthread_t mcount_sort_thread;
++
++struct elf_mcount_loc {
++      Elf_Ehdr *ehdr;
++      Elf_Shdr *init_data_sec;
++      uint64_t start_mcount_loc;
++      uint64_t stop_mcount_loc;
++};
++
++/* Sort the addresses stored between __start_mcount_loc to __stop_mcount_loc in vmlinux */
++static void *sort_mcount_loc(void *arg)
++{
++      struct elf_mcount_loc *emloc = (struct elf_mcount_loc *)arg;
++      uint64_t offset = emloc->start_mcount_loc - shdr_addr(emloc->init_data_sec)
++                                      + shdr_offset(emloc->init_data_sec);
++      uint64_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc;
++      unsigned char *start_loc = (void *)emloc->ehdr + offset;
++
++      qsort(start_loc, count/long_size, long_size, compare_extable);
++      return NULL;
++}
++
++/* Get the address of __start_mcount_loc and __stop_mcount_loc in System.map */
++static void get_mcount_loc(uint64_t *_start, uint64_t *_stop)
++{
++      FILE *file_start, *file_stop;
++      char start_buff[20];
++      char stop_buff[20];
++      int len = 0;
++
++      file_start = popen(" grep start_mcount System.map | awk '{print $1}' ", "r");
++      if (!file_start) {
++              fprintf(stderr, "get start_mcount_loc error!");
++              return;
++      }
++
++      file_stop = popen(" grep stop_mcount System.map | awk '{print $1}' ", "r");
++      if (!file_stop) {
++              fprintf(stderr, "get stop_mcount_loc error!");
++              pclose(file_start);
++              return;
++      }
++
++      while (fgets(start_buff, sizeof(start_buff), file_start) != NULL) {
++              len = strlen(start_buff);
++              start_buff[len - 1] = '\0';
++      }
++      *_start = strtoul(start_buff, NULL, 16);
++
++      while (fgets(stop_buff, sizeof(stop_buff), file_stop) != NULL) {
++              len = strlen(stop_buff);
++              stop_buff[len - 1] = '\0';
++      }
++      *_stop = strtoul(stop_buff, NULL, 16);
++
++      pclose(file_start);
++      pclose(file_stop);
++}
++#endif
++static int do_sort(Elf_Ehdr *ehdr,
++                 char const *const fname,
++                 table_sort_t custom_sort)
++{
++      int rc = -1;
++      Elf_Shdr *shdr_start;
++      Elf_Shdr *strtab_sec = NULL;
++      Elf_Shdr *symtab_sec = NULL;
++      Elf_Shdr *extab_sec = NULL;
++      Elf_Shdr *string_sec;
++      Elf_Sym *sym;
++      const Elf_Sym *symtab;
++      Elf32_Word *symtab_shndx = NULL;
++      Elf_Sym *sort_needed_sym = NULL;
++      Elf_Shdr *sort_needed_sec;
++      uint32_t *sort_needed_loc;
++      void *sym_start;
++      void *sym_end;
++      const char *secstrings;
++      const char *strtab;
++      char *extab_image;
++      int sort_need_index;
++      int symentsize;
++      int shentsize;
++      int idx;
++      int i;
++      unsigned int shnum;
++      unsigned int shstrndx;
++#ifdef MCOUNT_SORT_ENABLED
++      struct elf_mcount_loc mstruct = {0};
++      uint64_t _start_mcount_loc = 0;
++      uint64_t _stop_mcount_loc = 0;
++#endif
++#ifdef UNWINDER_ORC_ENABLED
++      unsigned int orc_ip_size = 0;
++      unsigned int orc_size = 0;
++      unsigned int orc_num_entries = 0;
++#endif
++
++      shdr_start = (Elf_Shdr *)((char *)ehdr + ehdr_shoff(ehdr));
++      shentsize = ehdr_shentsize(ehdr);
++
++      shstrndx = ehdr_shstrndx(ehdr);
++      if (shstrndx == SHN_XINDEX)
++              shstrndx = shdr_link(shdr_start);
++      string_sec = get_index(shdr_start, shentsize, shstrndx);
++      secstrings = (const char *)ehdr + shdr_offset(string_sec);
++
++      shnum = ehdr_shnum(ehdr);
++      if (shnum == SHN_UNDEF)
++              shnum = shdr_size(shdr_start);
++
++      for (i = 0; i < shnum; i++) {
++              Elf_Shdr *shdr = get_index(shdr_start, shentsize, i);
++
++              idx = shdr_name(shdr);
++              if (!strcmp(secstrings + idx, "__ex_table"))
++                      extab_sec = shdr;
++              if (!strcmp(secstrings + idx, ".symtab"))
++                      symtab_sec = shdr;
++              if (!strcmp(secstrings + idx, ".strtab"))
++                      strtab_sec = shdr;
++
++              if (shdr_type(shdr) == SHT_SYMTAB_SHNDX)
++                      symtab_shndx = (Elf32_Word *)((const char *)ehdr +
++                                                    shdr_offset(shdr));
++
++#ifdef MCOUNT_SORT_ENABLED
++              /* locate the .init.data section in vmlinux */
++              if (!strcmp(secstrings + idx, ".init.data")) {
++                      get_mcount_loc(&_start_mcount_loc, &_stop_mcount_loc);
++                      mstruct.ehdr = ehdr;
++                      mstruct.init_data_sec = shdr;
++                      mstruct.start_mcount_loc = _start_mcount_loc;
++                      mstruct.stop_mcount_loc = _stop_mcount_loc;
++              }
++#endif
++
++#ifdef UNWINDER_ORC_ENABLED
++              /* locate the ORC unwind tables */
++              if (!strcmp(secstrings + idx, ".orc_unwind_ip")) {
++                      orc_ip_size = shdr_size(shdr);
++                      g_orc_ip_table = (int *)((void *)ehdr +
++                                                 shdr_offset(shdr));
++              }
++              if (!strcmp(secstrings + idx, ".orc_unwind")) {
++                      orc_size = shdr_size(shdr);
++                      g_orc_table = (struct orc_entry *)((void *)ehdr +
++                                                           shdr_offset(shdr));
++              }
++#endif
++      } /* for loop */
++
++#ifdef UNWINDER_ORC_ENABLED
++      if (!g_orc_ip_table || !g_orc_table) {
++              fprintf(stderr,
++                      "incomplete ORC unwind tables in file: %s\n", fname);
++              goto out;
++      }
++
++      orc_num_entries = orc_ip_size / sizeof(int);
++      if (orc_ip_size % sizeof(int) != 0 ||
++          orc_size % sizeof(struct orc_entry) != 0 ||
++          orc_num_entries != orc_size / sizeof(struct orc_entry)) {
++              fprintf(stderr,
++                      "inconsistent ORC unwind table entries in file: %s\n",
++                      fname);
++              goto out;
++      }
++
++      /* create thread to sort ORC unwind tables concurrently */
++      if (pthread_create(&orc_sort_thread, NULL,
++                         sort_orctable, &orc_ip_size)) {
++              fprintf(stderr,
++                      "pthread_create orc_sort_thread failed '%s': %s\n",
++                      strerror(errno), fname);
++              goto out;
++      }
++#endif
++
++#ifdef MCOUNT_SORT_ENABLED
++      if (!mstruct.init_data_sec || !_start_mcount_loc || !_stop_mcount_loc) {
++              fprintf(stderr,
++                      "incomplete mcount's sort in file: %s\n",
++                      fname);
++              goto out;
++      }
++
++      /* create thread to sort mcount_loc concurrently */
++      if (pthread_create(&mcount_sort_thread, NULL, &sort_mcount_loc, &mstruct)) {
++              fprintf(stderr,
++                      "pthread_create mcount_sort_thread failed '%s': %s\n",
++                      strerror(errno), fname);
++              goto out;
++      }
++#endif
++      if (!extab_sec) {
++              fprintf(stderr, "no __ex_table in file: %s\n", fname);
++              goto out;
++      }
++
++      if (!symtab_sec) {
++              fprintf(stderr, "no .symtab in file: %s\n", fname);
++              goto out;
++      }
++
++      if (!strtab_sec) {
++              fprintf(stderr, "no .strtab in file: %s\n", fname);
++              goto out;
++      }
++
++      extab_image = (void *)ehdr + shdr_offset(extab_sec);
++      strtab = (const char *)ehdr + shdr_offset(strtab_sec);
++      symtab = (const Elf_Sym *)((const char *)ehdr + shdr_offset(symtab_sec));
++
++      if (custom_sort) {
++              custom_sort(extab_image, shdr_size(extab_sec));
++      } else {
++              int num_entries = shdr_size(extab_sec) / extable_ent_size;
++              qsort(extab_image, num_entries,
++                    extable_ent_size, compare_extable);
++      }
++
++      /* find the flag main_extable_sort_needed */
++      sym_start = (void *)ehdr + shdr_offset(symtab_sec);
++      sym_end = sym_start + shdr_size(symtab_sec);
++      symentsize = shdr_entsize(symtab_sec);
++
++      for (sym = sym_start; (void *)sym + symentsize < sym_end;
++           sym = (void *)sym + symentsize) {
++              if (sym_type(sym) != STT_OBJECT)
++                      continue;
++              if (!strcmp(strtab + sym_name(sym),
++                          "main_extable_sort_needed")) {
++                      sort_needed_sym = sym;
++                      break;
++              }
++      }
++
++      if (!sort_needed_sym) {
++              fprintf(stderr,
++                      "no main_extable_sort_needed symbol in file: %s\n",
++                      fname);
++              goto out;
++      }
++
++      sort_need_index = get_secindex(sym_shndx(sym),
++                                     ((void *)sort_needed_sym - (void *)symtab) / symentsize,
++                                     symtab_shndx);
++      sort_needed_sec = get_index(shdr_start, shentsize, sort_need_index);
++      sort_needed_loc = (void *)ehdr +
++              shdr_offset(sort_needed_sec) +
++              sym_value(sort_needed_sym) - shdr_addr(sort_needed_sec);
++
++      /* extable has been sorted, clear the flag */
++      w(0, sort_needed_loc);
++      rc = 0;
++
++out:
++#ifdef UNWINDER_ORC_ENABLED
++      if (orc_sort_thread) {
++              void *retval = NULL;
++              /* wait for ORC tables sort done */
++              rc = pthread_join(orc_sort_thread, &retval);
++              if (rc) {
++                      fprintf(stderr,
++                              "pthread_join failed '%s': %s\n",
++                              strerror(errno), fname);
++              } else if (retval) {
++                      rc = -1;
++                      fprintf(stderr,
++                              "failed to sort ORC tables '%s': %s\n",
++                              (char *)retval, fname);
++              }
++      }
++#endif
++
++#ifdef MCOUNT_SORT_ENABLED
++      if (mcount_sort_thread) {
++              void *retval = NULL;
++              /* wait for mcount sort done */
++              rc = pthread_join(mcount_sort_thread, &retval);
++              if (rc) {
++                      fprintf(stderr,
++                              "pthread_join failed '%s': %s\n",
++                              strerror(errno), fname);
++              } else if (retval) {
++                      rc = -1;
++                      fprintf(stderr,
++                              "failed to sort mcount '%s': %s\n",
++                              (char *)retval, fname);
++              }
++      }
++#endif
++      return rc;
++}
+ static int compare_relative_table(const void *a, const void *b)
+ {
+@@ -399,7 +812,6 @@ static void sort_relative_table_with_dat
+ static int do_file(char const *const fname, void *addr)
+ {
+-      int rc = -1;
+       Elf_Ehdr *ehdr = addr;
+       table_sort_t custom_sort = NULL;
+@@ -462,29 +874,64 @@ static int do_file(char const *const fna
+                   r2(&ehdr->e32.e_shentsize) != sizeof(Elf32_Shdr)) {
+                       fprintf(stderr,
+                               "unrecognized ET_EXEC/ET_DYN file: %s\n", fname);
+-                      break;
++                      return -1;
+               }
+-              rc = do_sort_32(ehdr, fname, custom_sort);
++
++              compare_extable         = compare_extable_32;
++              ehdr_shoff              = ehdr32_shoff;
++              ehdr_shentsize          = ehdr32_shentsize;
++              ehdr_shstrndx           = ehdr32_shstrndx;
++              ehdr_shnum              = ehdr32_shnum;
++              shdr_addr               = shdr32_addr;
++              shdr_offset             = shdr32_offset;
++              shdr_link               = shdr32_link;
++              shdr_size               = shdr32_size;
++              shdr_name               = shdr32_name;
++              shdr_type               = shdr32_type;
++              shdr_entsize            = shdr32_entsize;
++              sym_type                = sym32_type;
++              sym_name                = sym32_name;
++              sym_value               = sym32_value;
++              sym_shndx               = sym32_shndx;
++              long_size               = 4;
++              extable_ent_size        = 8;
+               break;
+       case ELFCLASS64:
+-              {
+               if (r2(&ehdr->e64.e_ehsize) != sizeof(Elf64_Ehdr) ||
+                   r2(&ehdr->e64.e_shentsize) != sizeof(Elf64_Shdr)) {
+                       fprintf(stderr,
+                               "unrecognized ET_EXEC/ET_DYN file: %s\n",
+                               fname);
+-                      break;
+-              }
+-              rc = do_sort_64(ehdr, fname, custom_sort);
++                      return -1;
+               }
++
++              compare_extable         = compare_extable_64;
++              ehdr_shoff              = ehdr64_shoff;
++              ehdr_shentsize          = ehdr64_shentsize;
++              ehdr_shstrndx           = ehdr64_shstrndx;
++              ehdr_shnum              = ehdr64_shnum;
++              shdr_addr               = shdr64_addr;
++              shdr_offset             = shdr64_offset;
++              shdr_link               = shdr64_link;
++              shdr_size               = shdr64_size;
++              shdr_name               = shdr64_name;
++              shdr_type               = shdr64_type;
++              shdr_entsize            = shdr64_entsize;
++              sym_type                = sym64_type;
++              sym_name                = sym64_name;
++              sym_value               = sym64_value;
++              sym_shndx               = sym64_shndx;
++              long_size               = 8;
++              extable_ent_size        = 16;
++
+               break;
+       default:
+               fprintf(stderr, "unrecognized ELF class %d %s\n",
+                       ehdr->e32.e_ident[EI_CLASS], fname);
+-              break;
++              return -1;
+       }
+-      return rc;
++      return do_sort(ehdr, fname, custom_sort);
+ }
+ int main(int argc, char *argv[])
+--- a/scripts/sorttable.h
++++ /dev/null
+@@ -1,485 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-only */
+-/*
+- * sorttable.h
+- *
+- * Added ORC unwind tables sort support and other updates:
+- * Copyright (C) 1999-2019 Alibaba Group Holding Limited. by:
+- * Shile Zhang <shile.zhang@linux.alibaba.com>
+- *
+- * Copyright 2011 - 2012 Cavium, Inc.
+- *
+- * Some of code was taken out of arch/x86/kernel/unwind_orc.c, written by:
+- * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com>
+- *
+- * Some of this code was taken out of recordmcount.h written by:
+- *
+- * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
+- * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
+- */
+-
+-#undef extable_ent_size
+-#undef compare_extable
+-#undef get_mcount_loc
+-#undef sort_mcount_loc
+-#undef elf_mcount_loc
+-#undef do_sort
+-#undef ehdr_shoff
+-#undef ehdr_shentsize
+-#undef ehdr_shstrndx
+-#undef ehdr_shnum
+-#undef shdr_addr
+-#undef shdr_offset
+-#undef shdr_link
+-#undef shdr_size
+-#undef shdr_name
+-#undef shdr_type
+-#undef shdr_entsize
+-#undef sym_type
+-#undef sym_name
+-#undef sym_value
+-#undef sym_shndx
+-#undef long_size
+-
+-#ifdef SORTTABLE_64
+-# define extable_ent_size     16
+-# define compare_extable      compare_extable_64
+-# define get_mcount_loc               get_mcount_loc_64
+-# define sort_mcount_loc      sort_mcount_loc_64
+-# define elf_mcount_loc               elf_mcount_loc_64
+-# define do_sort              do_sort_64
+-# define ehdr_shoff           ehdr64_shoff
+-# define ehdr_shentsize               ehdr64_shentsize
+-# define ehdr_shstrndx                ehdr64_shstrndx
+-# define ehdr_shnum           ehdr64_shnum
+-# define shdr_addr            shdr64_addr
+-# define shdr_offset          shdr64_offset
+-# define shdr_link            shdr64_link
+-# define shdr_size            shdr64_size
+-# define shdr_name            shdr64_name
+-# define shdr_type            shdr64_type
+-# define shdr_entsize         shdr64_entsize
+-# define sym_type             sym64_type
+-# define sym_name             sym64_name
+-# define sym_value            sym64_value
+-# define sym_shndx            sym64_shndx
+-# define long_size            8
+-#else
+-# define extable_ent_size     8
+-# define compare_extable      compare_extable_32
+-# define get_mcount_loc               get_mcount_loc_32
+-# define sort_mcount_loc      sort_mcount_loc_32
+-# define elf_mcount_loc               elf_mcount_loc_32
+-# define do_sort              do_sort_32
+-# define ehdr_shoff           ehdr32_shoff
+-# define ehdr_shentsize               ehdr32_shentsize
+-# define ehdr_shstrndx                ehdr32_shstrndx
+-# define ehdr_shnum           ehdr32_shnum
+-# define shdr_addr            shdr32_addr
+-# define shdr_offset          shdr32_offset
+-# define shdr_link            shdr32_link
+-# define shdr_size            shdr32_size
+-# define shdr_name            shdr32_name
+-# define shdr_type            shdr32_type
+-# define shdr_entsize         shdr32_entsize
+-# define sym_type             sym32_type
+-# define sym_name             sym32_name
+-# define sym_value            sym32_value
+-# define sym_shndx            sym32_shndx
+-# define long_size            4
+-#endif
+-
+-#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+-/* ORC unwinder only support X86_64 */
+-#include <asm/orc_types.h>
+-
+-#define ERRSTR_MAXSZ  256
+-
+-char g_err[ERRSTR_MAXSZ];
+-int *g_orc_ip_table;
+-struct orc_entry *g_orc_table;
+-
+-pthread_t orc_sort_thread;
+-
+-static inline unsigned long orc_ip(const int *ip)
+-{
+-      return (unsigned long)ip + *ip;
+-}
+-
+-static int orc_sort_cmp(const void *_a, const void *_b)
+-{
+-      struct orc_entry *orc_a, *orc_b;
+-      const int *a = g_orc_ip_table + *(int *)_a;
+-      const int *b = g_orc_ip_table + *(int *)_b;
+-      unsigned long a_val = orc_ip(a);
+-      unsigned long b_val = orc_ip(b);
+-
+-      if (a_val > b_val)
+-              return 1;
+-      if (a_val < b_val)
+-              return -1;
+-
+-      /*
+-       * The "weak" section terminator entries need to always be on the left
+-       * to ensure the lookup code skips them in favor of real entries.
+-       * These terminator entries exist to handle any gaps created by
+-       * whitelisted .o files which didn't get objtool generation.
+-       */
+-      orc_a = g_orc_table + (a - g_orc_ip_table);
+-      orc_b = g_orc_table + (b - g_orc_ip_table);
+-      if (orc_a->type == ORC_TYPE_UNDEFINED && orc_b->type == ORC_TYPE_UNDEFINED)
+-              return 0;
+-      return orc_a->type == ORC_TYPE_UNDEFINED ? -1 : 1;
+-}
+-
+-static void *sort_orctable(void *arg)
+-{
+-      int i;
+-      int *idxs = NULL;
+-      int *tmp_orc_ip_table = NULL;
+-      struct orc_entry *tmp_orc_table = NULL;
+-      unsigned int *orc_ip_size = (unsigned int *)arg;
+-      unsigned int num_entries = *orc_ip_size / sizeof(int);
+-      unsigned int orc_size = num_entries * sizeof(struct orc_entry);
+-
+-      idxs = (int *)malloc(*orc_ip_size);
+-      if (!idxs) {
+-              snprintf(g_err, ERRSTR_MAXSZ, "malloc idxs: %s",
+-                       strerror(errno));
+-              pthread_exit(g_err);
+-      }
+-
+-      tmp_orc_ip_table = (int *)malloc(*orc_ip_size);
+-      if (!tmp_orc_ip_table) {
+-              snprintf(g_err, ERRSTR_MAXSZ, "malloc tmp_orc_ip_table: %s",
+-                       strerror(errno));
+-              pthread_exit(g_err);
+-      }
+-
+-      tmp_orc_table = (struct orc_entry *)malloc(orc_size);
+-      if (!tmp_orc_table) {
+-              snprintf(g_err, ERRSTR_MAXSZ, "malloc tmp_orc_table: %s",
+-                       strerror(errno));
+-              pthread_exit(g_err);
+-      }
+-
+-      /* initialize indices array, convert ip_table to absolute address */
+-      for (i = 0; i < num_entries; i++) {
+-              idxs[i] = i;
+-              tmp_orc_ip_table[i] = g_orc_ip_table[i] + i * sizeof(int);
+-      }
+-      memcpy(tmp_orc_table, g_orc_table, orc_size);
+-
+-      qsort(idxs, num_entries, sizeof(int), orc_sort_cmp);
+-
+-      for (i = 0; i < num_entries; i++) {
+-              if (idxs[i] == i)
+-                      continue;
+-
+-              /* convert back to relative address */
+-              g_orc_ip_table[i] = tmp_orc_ip_table[idxs[i]] - i * sizeof(int);
+-              g_orc_table[i] = tmp_orc_table[idxs[i]];
+-      }
+-
+-      free(idxs);
+-      free(tmp_orc_ip_table);
+-      free(tmp_orc_table);
+-      pthread_exit(NULL);
+-}
+-#endif
+-
+-#ifdef MCOUNT_SORT_ENABLED
+-pthread_t mcount_sort_thread;
+-
+-struct elf_mcount_loc {
+-      Elf_Ehdr *ehdr;
+-      Elf_Shdr *init_data_sec;
+-      uint64_t start_mcount_loc;
+-      uint64_t stop_mcount_loc;
+-};
+-
+-/* Sort the addresses stored between __start_mcount_loc to __stop_mcount_loc in vmlinux */
+-static void *sort_mcount_loc(void *arg)
+-{
+-      struct elf_mcount_loc *emloc = (struct elf_mcount_loc *)arg;
+-      uint64_t offset = emloc->start_mcount_loc - shdr_addr(emloc->init_data_sec)
+-                                      + shdr_offset(emloc->init_data_sec);
+-      uint64_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc;
+-      unsigned char *start_loc = (void *)emloc->ehdr + offset;
+-
+-      qsort(start_loc, count/long_size, long_size, compare_extable);
+-      return NULL;
+-}
+-
+-/* Get the address of __start_mcount_loc and __stop_mcount_loc in System.map */
+-static void get_mcount_loc(uint64_t *_start, uint64_t *_stop)
+-{
+-      FILE *file_start, *file_stop;
+-      char start_buff[20];
+-      char stop_buff[20];
+-      int len = 0;
+-
+-      file_start = popen(" grep start_mcount System.map | awk '{print $1}' ", "r");
+-      if (!file_start) {
+-              fprintf(stderr, "get start_mcount_loc error!");
+-              return;
+-      }
+-
+-      file_stop = popen(" grep stop_mcount System.map | awk '{print $1}' ", "r");
+-      if (!file_stop) {
+-              fprintf(stderr, "get stop_mcount_loc error!");
+-              pclose(file_start);
+-              return;
+-      }
+-
+-      while (fgets(start_buff, sizeof(start_buff), file_start) != NULL) {
+-              len = strlen(start_buff);
+-              start_buff[len - 1] = '\0';
+-      }
+-      *_start = strtoul(start_buff, NULL, 16);
+-
+-      while (fgets(stop_buff, sizeof(stop_buff), file_stop) != NULL) {
+-              len = strlen(stop_buff);
+-              stop_buff[len - 1] = '\0';
+-      }
+-      *_stop = strtoul(stop_buff, NULL, 16);
+-
+-      pclose(file_start);
+-      pclose(file_stop);
+-}
+-#endif
+-static int do_sort(Elf_Ehdr *ehdr,
+-                 char const *const fname,
+-                 table_sort_t custom_sort)
+-{
+-      int rc = -1;
+-      Elf_Shdr *shdr_start;
+-      Elf_Shdr *strtab_sec = NULL;
+-      Elf_Shdr *symtab_sec = NULL;
+-      Elf_Shdr *extab_sec = NULL;
+-      Elf_Shdr *string_sec;
+-      Elf_Sym *sym;
+-      const Elf_Sym *symtab;
+-      Elf32_Word *symtab_shndx = NULL;
+-      Elf_Sym *sort_needed_sym = NULL;
+-      Elf_Shdr *sort_needed_sec;
+-      uint32_t *sort_needed_loc;
+-      void *sym_start;
+-      void *sym_end;
+-      const char *secstrings;
+-      const char *strtab;
+-      char *extab_image;
+-      int sort_need_index;
+-      int symentsize;
+-      int shentsize;
+-      int idx;
+-      int i;
+-      unsigned int shnum;
+-      unsigned int shstrndx;
+-#ifdef MCOUNT_SORT_ENABLED
+-      struct elf_mcount_loc mstruct = {0};
+-      uint64_t _start_mcount_loc = 0;
+-      uint64_t _stop_mcount_loc = 0;
+-#endif
+-#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+-      unsigned int orc_ip_size = 0;
+-      unsigned int orc_size = 0;
+-      unsigned int orc_num_entries = 0;
+-#endif
+-
+-      shdr_start = (Elf_Shdr *)((char *)ehdr + ehdr_shoff(ehdr));
+-      shentsize = ehdr_shentsize(ehdr);
+-
+-      shstrndx = ehdr_shstrndx(ehdr);
+-      if (shstrndx == SHN_XINDEX)
+-              shstrndx = shdr_link(shdr_start);
+-      string_sec = get_index(shdr_start, shentsize, shstrndx);
+-      secstrings = (const char *)ehdr + shdr_offset(string_sec);
+-
+-      shnum = ehdr_shnum(ehdr);
+-      if (shnum == SHN_UNDEF)
+-              shnum = shdr_size(shdr_start);
+-
+-      for (i = 0; i < shnum; i++) {
+-              Elf_Shdr *shdr = get_index(shdr_start, shentsize, i);
+-
+-              idx = shdr_name(shdr);
+-              if (!strcmp(secstrings + idx, "__ex_table"))
+-                      extab_sec = shdr;
+-              if (!strcmp(secstrings + idx, ".symtab"))
+-                      symtab_sec = shdr;
+-              if (!strcmp(secstrings + idx, ".strtab"))
+-                      strtab_sec = shdr;
+-
+-              if (shdr_type(shdr) == SHT_SYMTAB_SHNDX)
+-                      symtab_shndx = (Elf32_Word *)((const char *)ehdr +
+-                                                    shdr_offset(shdr));
+-
+-#ifdef MCOUNT_SORT_ENABLED
+-              /* locate the .init.data section in vmlinux */
+-              if (!strcmp(secstrings + idx, ".init.data")) {
+-                      get_mcount_loc(&_start_mcount_loc, &_stop_mcount_loc);
+-                      mstruct.ehdr = ehdr;
+-                      mstruct.init_data_sec = shdr;
+-                      mstruct.start_mcount_loc = _start_mcount_loc;
+-                      mstruct.stop_mcount_loc = _stop_mcount_loc;
+-              }
+-#endif
+-
+-#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+-              /* locate the ORC unwind tables */
+-              if (!strcmp(secstrings + idx, ".orc_unwind_ip")) {
+-                      orc_ip_size = shdr_size(shdr);
+-                      g_orc_ip_table = (int *)((void *)ehdr +
+-                                                 shdr_offset(shdr));
+-              }
+-              if (!strcmp(secstrings + idx, ".orc_unwind")) {
+-                      orc_size = shdr_size(shdr);
+-                      g_orc_table = (struct orc_entry *)((void *)ehdr +
+-                                                           shdr_offset(shdr));
+-              }
+-#endif
+-      } /* for loop */
+-
+-#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+-      if (!g_orc_ip_table || !g_orc_table) {
+-              fprintf(stderr,
+-                      "incomplete ORC unwind tables in file: %s\n", fname);
+-              goto out;
+-      }
+-
+-      orc_num_entries = orc_ip_size / sizeof(int);
+-      if (orc_ip_size % sizeof(int) != 0 ||
+-          orc_size % sizeof(struct orc_entry) != 0 ||
+-          orc_num_entries != orc_size / sizeof(struct orc_entry)) {
+-              fprintf(stderr,
+-                      "inconsistent ORC unwind table entries in file: %s\n",
+-                      fname);
+-              goto out;
+-      }
+-
+-      /* create thread to sort ORC unwind tables concurrently */
+-      if (pthread_create(&orc_sort_thread, NULL,
+-                         sort_orctable, &orc_ip_size)) {
+-              fprintf(stderr,
+-                      "pthread_create orc_sort_thread failed '%s': %s\n",
+-                      strerror(errno), fname);
+-              goto out;
+-      }
+-#endif
+-
+-#ifdef MCOUNT_SORT_ENABLED
+-      if (!mstruct.init_data_sec || !_start_mcount_loc || !_stop_mcount_loc) {
+-              fprintf(stderr,
+-                      "incomplete mcount's sort in file: %s\n",
+-                      fname);
+-              goto out;
+-      }
+-
+-      /* create thread to sort mcount_loc concurrently */
+-      if (pthread_create(&mcount_sort_thread, NULL, &sort_mcount_loc, &mstruct)) {
+-              fprintf(stderr,
+-                      "pthread_create mcount_sort_thread failed '%s': %s\n",
+-                      strerror(errno), fname);
+-              goto out;
+-      }
+-#endif
+-      if (!extab_sec) {
+-              fprintf(stderr, "no __ex_table in file: %s\n", fname);
+-              goto out;
+-      }
+-
+-      if (!symtab_sec) {
+-              fprintf(stderr, "no .symtab in file: %s\n", fname);
+-              goto out;
+-      }
+-
+-      if (!strtab_sec) {
+-              fprintf(stderr, "no .strtab in file: %s\n", fname);
+-              goto out;
+-      }
+-
+-      extab_image = (void *)ehdr + shdr_offset(extab_sec);
+-      strtab = (const char *)ehdr + shdr_offset(strtab_sec);
+-      symtab = (const Elf_Sym *)((const char *)ehdr + shdr_offset(symtab_sec));
+-
+-      if (custom_sort) {
+-              custom_sort(extab_image, shdr_size(extab_sec));
+-      } else {
+-              int num_entries = shdr_size(extab_sec) / extable_ent_size;
+-              qsort(extab_image, num_entries,
+-                    extable_ent_size, compare_extable);
+-      }
+-
+-      /* find the flag main_extable_sort_needed */
+-      sym_start = (void *)ehdr + shdr_offset(symtab_sec);
+-      sym_end = sym_start + shdr_size(symtab_sec);
+-      symentsize = shdr_entsize(symtab_sec);
+-
+-      for (sym = sym_start; (void *)sym + symentsize < sym_end;
+-           sym = (void *)sym + symentsize) {
+-              if (sym_type(sym) != STT_OBJECT)
+-                      continue;
+-              if (!strcmp(strtab + sym_name(sym),
+-                          "main_extable_sort_needed")) {
+-                      sort_needed_sym = sym;
+-                      break;
+-              }
+-      }
+-
+-      if (!sort_needed_sym) {
+-              fprintf(stderr,
+-                      "no main_extable_sort_needed symbol in file: %s\n",
+-                      fname);
+-              goto out;
+-      }
+-
+-      sort_need_index = get_secindex(sym_shndx(sym),
+-                                     ((void *)sort_needed_sym - (void *)symtab) / symentsize,
+-                                     symtab_shndx);
+-      sort_needed_sec = get_index(shdr_start, shentsize, sort_need_index);
+-      sort_needed_loc = (void *)ehdr +
+-              shdr_offset(sort_needed_sec) +
+-              sym_value(sort_needed_sym) - shdr_addr(sort_needed_sec);
+-
+-      /* extable has been sorted, clear the flag */
+-      w(0, sort_needed_loc);
+-      rc = 0;
+-
+-out:
+-#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+-      if (orc_sort_thread) {
+-              void *retval = NULL;
+-              /* wait for ORC tables sort done */
+-              rc = pthread_join(orc_sort_thread, &retval);
+-              if (rc) {
+-                      fprintf(stderr,
+-                              "pthread_join failed '%s': %s\n",
+-                              strerror(errno), fname);
+-              } else if (retval) {
+-                      rc = -1;
+-                      fprintf(stderr,
+-                              "failed to sort ORC tables '%s': %s\n",
+-                              (char *)retval, fname);
+-              }
+-      }
+-#endif
+-
+-#ifdef MCOUNT_SORT_ENABLED
+-      if (mcount_sort_thread) {
+-              void *retval = NULL;
+-              /* wait for mcount sort done */
+-              rc = pthread_join(mcount_sort_thread, &retval);
+-              if (rc) {
+-                      fprintf(stderr,
+-                              "pthread_join failed '%s': %s\n",
+-                              strerror(errno), fname);
+-              } else if (retval) {
+-                      rc = -1;
+-                      fprintf(stderr,
+-                              "failed to sort mcount '%s': %s\n",
+-                              (char *)retval, fname);
+-              }
+-      }
+-#endif
+-      return rc;
+-}
diff --git a/queue-6.12/scripts-sorttable-remove-unneeded-elf_rel.patch b/queue-6.12/scripts-sorttable-remove-unneeded-elf_rel.patch
new file mode 100644 (file)
index 0000000..aa9b032
--- /dev/null
@@ -0,0 +1,115 @@
+From prvs=262951c835=andrey.grodzovsky@crowdstrike.com Thu Jun 18 21:16:00 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:17 -0400
+Subject: scripts/sorttable: Remove unneeded Elf_Rel
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <984bf8d32a9080de6819dede14055b154f6d619d.1781809917.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 6f2c2f93a190467cebd6ebd03feb49514fead5ca ]
+
+The code had references to initialize the Elf_Rel relocation tables, but
+it was never used. Remove it.
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Link: https://lore.kernel.org/20250105162344.515342233@goodmis.org
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.h |   23 ++---------------------
+ 1 file changed, 2 insertions(+), 21 deletions(-)
+
+--- a/scripts/sorttable.h
++++ b/scripts/sorttable.h
+@@ -26,7 +26,6 @@
+ #undef Elf_Addr
+ #undef Elf_Ehdr
+ #undef Elf_Shdr
+-#undef Elf_Rel
+ #undef Elf_Sym
+ #undef ELF_ST_TYPE
+ #undef uint_t
+@@ -42,7 +41,6 @@
+ # define Elf_Addr             Elf64_Addr
+ # define Elf_Ehdr             Elf64_Ehdr
+ # define Elf_Shdr             Elf64_Shdr
+-# define Elf_Rel              Elf64_Rel
+ # define Elf_Sym              Elf64_Sym
+ # define ELF_ST_TYPE          ELF64_ST_TYPE
+ # define uint_t                       uint64_t
+@@ -57,7 +55,6 @@
+ # define Elf_Addr             Elf32_Addr
+ # define Elf_Ehdr             Elf32_Ehdr
+ # define Elf_Shdr             Elf32_Shdr
+-# define Elf_Rel              Elf32_Rel
+ # define Elf_Sym              Elf32_Sym
+ # define ELF_ST_TYPE          ELF32_ST_TYPE
+ # define uint_t                       uint32_t
+@@ -248,14 +245,10 @@ static int do_sort(Elf_Ehdr *ehdr,
+       Elf32_Word *symtab_shndx = NULL;
+       Elf_Sym *sort_needed_sym = NULL;
+       Elf_Shdr *sort_needed_sec;
+-      Elf_Rel *relocs = NULL;
+-      int relocs_size = 0;
+       uint32_t *sort_needed_loc;
+       const char *secstrings;
+       const char *strtab;
+       char *extab_image;
+-      int extab_index = 0;
+-      int i;
+       int idx;
+       unsigned int shnum;
+       unsigned int shstrndx;
+@@ -279,23 +272,15 @@ static int do_sort(Elf_Ehdr *ehdr,
+       if (shnum == SHN_UNDEF)
+               shnum = _r(&shdr[0].sh_size);
+-      for (i = 0, s = shdr; s < shdr + shnum; i++, s++) {
++      for (s = shdr; s < shdr + shnum; s++) {
+               idx = r(&s->sh_name);
+-              if (!strcmp(secstrings + idx, "__ex_table")) {
++              if (!strcmp(secstrings + idx, "__ex_table"))
+                       extab_sec = s;
+-                      extab_index = i;
+-              }
+               if (!strcmp(secstrings + idx, ".symtab"))
+                       symtab_sec = s;
+               if (!strcmp(secstrings + idx, ".strtab"))
+                       strtab_sec = s;
+-              if ((r(&s->sh_type) == SHT_REL ||
+-                   r(&s->sh_type) == SHT_RELA) &&
+-                  r(&s->sh_info) == extab_index) {
+-                      relocs = (void *)ehdr + _r(&s->sh_offset);
+-                      relocs_size = _r(&s->sh_size);
+-              }
+               if (r(&s->sh_type) == SHT_SYMTAB_SHNDX)
+                       symtab_shndx = (Elf32_Word *)((const char *)ehdr +
+                                                     _r(&s->sh_offset));
+@@ -397,10 +382,6 @@ static int do_sort(Elf_Ehdr *ehdr,
+                     extable_ent_size, compare_extable);
+       }
+-      /* If there were relocations, we no longer need them. */
+-      if (relocs)
+-              memset(relocs, 0, relocs_size);
+-
+       /* find the flag main_extable_sort_needed */
+       for (sym = (void *)ehdr + _r(&symtab_sec->sh_offset);
+            sym < sym + _r(&symtab_sec->sh_size) / sizeof(Elf_Sym);
diff --git a/queue-6.12/scripts-sorttable-remove-unused-macro-defines.patch b/queue-6.12/scripts-sorttable-remove-unused-macro-defines.patch
new file mode 100644 (file)
index 0000000..07e1128
--- /dev/null
@@ -0,0 +1,101 @@
+From prvs=262951c835=andrey.grodzovsky@crowdstrike.com Thu Jun 18 21:15:58 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:15 -0400
+Subject: scripts/sorttable: Remove unused macro defines
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <f1cd060da6cd86ab48f12660a85f7059f3aa016c.1781809913.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 28b24394c6e9a3166fcb4480cba054562526657c ]
+
+The code of sorttable.h was copied from the recordmcount.h  which defined
+a bunch of Elf MACROs so that they could be used between 32bit and 64bit
+functions. But there's several MACROs that sorttable.h does not use but
+was copied over. Remove them to clean up the code.
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Link: https://lore.kernel.org/20250105162344.128870118@goodmis.org
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.h |   27 ---------------------------
+ 1 file changed, 27 deletions(-)
+
+--- a/scripts/sorttable.h
++++ b/scripts/sorttable.h
+@@ -27,19 +27,10 @@
+ #undef Elf_Ehdr
+ #undef Elf_Shdr
+ #undef Elf_Rel
+-#undef Elf_Rela
+ #undef Elf_Sym
+-#undef ELF_R_SYM
+-#undef Elf_r_sym
+-#undef ELF_R_INFO
+-#undef Elf_r_info
+-#undef ELF_ST_BIND
+ #undef ELF_ST_TYPE
+-#undef fn_ELF_R_SYM
+-#undef fn_ELF_R_INFO
+ #undef uint_t
+ #undef _r
+-#undef _w
+ #ifdef SORTTABLE_64
+ # define extable_ent_size     16
+@@ -52,19 +43,10 @@
+ # define Elf_Ehdr             Elf64_Ehdr
+ # define Elf_Shdr             Elf64_Shdr
+ # define Elf_Rel              Elf64_Rel
+-# define Elf_Rela             Elf64_Rela
+ # define Elf_Sym              Elf64_Sym
+-# define ELF_R_SYM            ELF64_R_SYM
+-# define Elf_r_sym            Elf64_r_sym
+-# define ELF_R_INFO           ELF64_R_INFO
+-# define Elf_r_info           Elf64_r_info
+-# define ELF_ST_BIND          ELF64_ST_BIND
+ # define ELF_ST_TYPE          ELF64_ST_TYPE
+-# define fn_ELF_R_SYM         fn_ELF64_R_SYM
+-# define fn_ELF_R_INFO                fn_ELF64_R_INFO
+ # define uint_t                       uint64_t
+ # define _r                   r8
+-# define _w                   w8
+ #else
+ # define extable_ent_size     8
+ # define compare_extable      compare_extable_32
+@@ -76,19 +58,10 @@
+ # define Elf_Ehdr             Elf32_Ehdr
+ # define Elf_Shdr             Elf32_Shdr
+ # define Elf_Rel              Elf32_Rel
+-# define Elf_Rela             Elf32_Rela
+ # define Elf_Sym              Elf32_Sym
+-# define ELF_R_SYM            ELF32_R_SYM
+-# define Elf_r_sym            Elf32_r_sym
+-# define ELF_R_INFO           ELF32_R_INFO
+-# define Elf_r_info           Elf32_r_info
+-# define ELF_ST_BIND          ELF32_ST_BIND
+ # define ELF_ST_TYPE          ELF32_ST_TYPE
+-# define fn_ELF_R_SYM         fn_ELF32_R_SYM
+-# define fn_ELF_R_INFO                fn_ELF32_R_INFO
+ # define uint_t                       uint32_t
+ # define _r                   r
+-# define _w                   w
+ #endif
+ #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
diff --git a/queue-6.12/scripts-sorttable-remove-unused-write-functions.patch b/queue-6.12/scripts-sorttable-remove-unused-write-functions.patch
new file mode 100644 (file)
index 0000000..918ea58
--- /dev/null
@@ -0,0 +1,99 @@
+From stable+bounces-267208-greg=kroah.com@vger.kernel.org Thu Jun 18 21:15:59 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:16 -0400
+Subject: scripts/sorttable: Remove unused write functions
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <b4b7893593e70929d097a18d2838814bee99b631.1781809915.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 4f48a28b37d594dab38092514a42ae9f4b781553 ]
+
+The code of sorttable.h was copied from the recordmcount.h  which defined
+various write functions for different sizes (2, 4, 8 byte lengths). But
+sorttable only uses the 4 byte writes. Remove the extra versions as they
+are not used.
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Link: https://lore.kernel.org/20250105162344.314385504@goodmis.org
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.c |   26 --------------------------
+ 1 file changed, 26 deletions(-)
+
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -68,8 +68,6 @@ static uint32_t (*r)(const uint32_t *);
+ static uint16_t (*r2)(const uint16_t *);
+ static uint64_t (*r8)(const uint64_t *);
+ static void (*w)(uint32_t, uint32_t *);
+-static void (*w2)(uint16_t, uint16_t *);
+-static void (*w8)(uint64_t, uint64_t *);
+ typedef void (*table_sort_t)(char *, int);
+ /*
+@@ -146,31 +144,11 @@ static void wbe(uint32_t val, uint32_t *
+       put_unaligned_be32(val, x);
+ }
+-static void w2be(uint16_t val, uint16_t *x)
+-{
+-      put_unaligned_be16(val, x);
+-}
+-
+-static void w8be(uint64_t val, uint64_t *x)
+-{
+-      put_unaligned_be64(val, x);
+-}
+-
+ static void wle(uint32_t val, uint32_t *x)
+ {
+       put_unaligned_le32(val, x);
+ }
+-static void w2le(uint16_t val, uint16_t *x)
+-{
+-      put_unaligned_le16(val, x);
+-}
+-
+-static void w8le(uint64_t val, uint64_t *x)
+-{
+-      put_unaligned_le64(val, x);
+-}
+-
+ /*
+  * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of
+  * the way to -256..-1, to avoid conflicting with real section
+@@ -277,16 +255,12 @@ static int do_file(char const *const fna
+               r2      = r2le;
+               r8      = r8le;
+               w       = wle;
+-              w2      = w2le;
+-              w8      = w8le;
+               break;
+       case ELFDATA2MSB:
+               r       = rbe;
+               r2      = r2be;
+               r8      = r8be;
+               w       = wbe;
+-              w2      = w2be;
+-              w8      = w8be;
+               break;
+       default:
+               fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
diff --git a/queue-6.12/scripts-sorttable-replace-elf_shdr-macro-with-a-union.patch b/queue-6.12/scripts-sorttable-replace-elf_shdr-macro-with-a-union.patch
new file mode 100644 (file)
index 0000000..98127f1
--- /dev/null
@@ -0,0 +1,253 @@
+From stable+bounces-267210-greg=kroah.com@vger.kernel.org Thu Jun 18 21:16:06 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:21 -0400
+Subject: scripts/sorttable: Replace Elf_Shdr Macro with a union
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <a5f3a078f5a3b599df8fb883345b4aff36b7d3d8.1781809929.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 545f6cf8f4c9a268e0bab2637f1d279679befdbf ]
+
+In order to remove the double #include of sorttable.h for 64 and 32 bit
+to create duplicate functions for both, replace the Elf_Shdr macro with a
+union that defines both Elf64_Shdr and Elf32_Shdr, with field e64 for the
+64bit version, and e32 for the 32bit version.
+
+It can then use the macro etype to get the proper value.
+
+This will eventually be replaced with just single functions that can
+handle both 32bit and 64bit ELF parsing.
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Link: https://lore.kernel.org/20250105162345.339462681@goodmis.org
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.c |   10 +++++++
+ scripts/sorttable.h |   74 ++++++++++++++++++++++++++++------------------------
+ 2 files changed, 51 insertions(+), 33 deletions(-)
+
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -69,6 +69,11 @@ typedef union {
+       Elf64_Ehdr      e64;
+ } Elf_Ehdr;
++typedef union {
++      Elf32_Shdr      e32;
++      Elf64_Shdr      e64;
++} Elf_Shdr;
++
+ static uint32_t (*r)(const uint32_t *);
+ static uint16_t (*r2)(const uint16_t *);
+ static uint64_t (*r8)(const uint64_t *);
+@@ -198,6 +203,11 @@ static int compare_extable_64(const void
+       return av > bv;
+ }
++static inline void *get_index(void *start, int entsize, int index)
++{
++      return start + (entsize * index);
++}
++
+ /* 32 bit and 64 bit are very similar */
+ #include "sorttable.h"
+ #define SORTTABLE_64
+--- a/scripts/sorttable.h
++++ b/scripts/sorttable.h
+@@ -23,7 +23,6 @@
+ #undef sort_mcount_loc
+ #undef elf_mcount_loc
+ #undef do_sort
+-#undef Elf_Shdr
+ #undef Elf_Sym
+ #undef ELF_ST_TYPE
+ #undef uint_t
+@@ -37,7 +36,6 @@
+ # define sort_mcount_loc      sort_mcount_loc_64
+ # define elf_mcount_loc               elf_mcount_loc_64
+ # define do_sort              do_sort_64
+-# define Elf_Shdr             Elf64_Shdr
+ # define Elf_Sym              Elf64_Sym
+ # define ELF_ST_TYPE          ELF64_ST_TYPE
+ # define uint_t                       uint64_t
+@@ -50,7 +48,6 @@
+ # define sort_mcount_loc      sort_mcount_loc_32
+ # define elf_mcount_loc               elf_mcount_loc_32
+ # define do_sort              do_sort_32
+-# define Elf_Shdr             Elf32_Shdr
+ # define Elf_Sym              Elf32_Sym
+ # define ELF_ST_TYPE          ELF32_ST_TYPE
+ # define uint_t                       uint32_t
+@@ -171,8 +168,8 @@ struct elf_mcount_loc {
+ static void *sort_mcount_loc(void *arg)
+ {
+       struct elf_mcount_loc *emloc = (struct elf_mcount_loc *)arg;
+-      uint_t offset = emloc->start_mcount_loc - _r(&(emloc->init_data_sec)->sh_addr)
+-                                      + _r(&(emloc->init_data_sec)->sh_offset);
++      uint_t offset = emloc->start_mcount_loc - _r(&(emloc->init_data_sec)->etype.sh_addr)
++                                      + _r(&(emloc->init_data_sec)->etype.sh_offset);
+       uint_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc;
+       unsigned char *start_loc = (void *)emloc->ehdr + offset;
+@@ -222,10 +219,11 @@ static int do_sort(Elf_Ehdr *ehdr,
+                  table_sort_t custom_sort)
+ {
+       int rc = -1;
+-      Elf_Shdr *s, *shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->etype.e_shoff));
++      Elf_Shdr *shdr_start;
+       Elf_Shdr *strtab_sec = NULL;
+       Elf_Shdr *symtab_sec = NULL;
+       Elf_Shdr *extab_sec = NULL;
++      Elf_Shdr *string_sec;
+       Elf_Sym *sym;
+       const Elf_Sym *symtab;
+       Elf32_Word *symtab_shndx = NULL;
+@@ -235,7 +233,10 @@ static int do_sort(Elf_Ehdr *ehdr,
+       const char *secstrings;
+       const char *strtab;
+       char *extab_image;
++      int sort_need_index;
++      int shentsize;
+       int idx;
++      int i;
+       unsigned int shnum;
+       unsigned int shstrndx;
+ #ifdef MCOUNT_SORT_ENABLED
+@@ -249,34 +250,40 @@ static int do_sort(Elf_Ehdr *ehdr,
+       unsigned int orc_num_entries = 0;
+ #endif
++      shdr_start = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->etype.e_shoff));
++      shentsize = r2(&ehdr->etype.e_shentsize);
++
+       shstrndx = r2(&ehdr->etype.e_shstrndx);
+       if (shstrndx == SHN_XINDEX)
+-              shstrndx = r(&shdr[0].sh_link);
+-      secstrings = (const char *)ehdr + _r(&shdr[shstrndx].sh_offset);
++              shstrndx = r(&shdr_start->etype.sh_link);
++      string_sec = get_index(shdr_start, shentsize, shstrndx);
++      secstrings = (const char *)ehdr + _r(&string_sec->etype.sh_offset);
+       shnum = r2(&ehdr->etype.e_shnum);
+       if (shnum == SHN_UNDEF)
+-              shnum = _r(&shdr[0].sh_size);
++              shnum = _r(&shdr_start->etype.sh_size);
++
++      for (i = 0; i < shnum; i++) {
++              Elf_Shdr *shdr = get_index(shdr_start, shentsize, i);
+-      for (s = shdr; s < shdr + shnum; s++) {
+-              idx = r(&s->sh_name);
++              idx = r(&shdr->etype.sh_name);
+               if (!strcmp(secstrings + idx, "__ex_table"))
+-                      extab_sec = s;
++                      extab_sec = shdr;
+               if (!strcmp(secstrings + idx, ".symtab"))
+-                      symtab_sec = s;
++                      symtab_sec = shdr;
+               if (!strcmp(secstrings + idx, ".strtab"))
+-                      strtab_sec = s;
++                      strtab_sec = shdr;
+-              if (r(&s->sh_type) == SHT_SYMTAB_SHNDX)
++              if (r(&shdr->etype.sh_type) == SHT_SYMTAB_SHNDX)
+                       symtab_shndx = (Elf32_Word *)((const char *)ehdr +
+-                                                    _r(&s->sh_offset));
++                                                    _r(&shdr->etype.sh_offset));
+ #ifdef MCOUNT_SORT_ENABLED
+               /* locate the .init.data section in vmlinux */
+               if (!strcmp(secstrings + idx, ".init.data")) {
+                       get_mcount_loc(&_start_mcount_loc, &_stop_mcount_loc);
+                       mstruct.ehdr = ehdr;
+-                      mstruct.init_data_sec = s;
++                      mstruct.init_data_sec = shdr;
+                       mstruct.start_mcount_loc = _start_mcount_loc;
+                       mstruct.stop_mcount_loc = _stop_mcount_loc;
+               }
+@@ -285,14 +292,14 @@ static int do_sort(Elf_Ehdr *ehdr,
+ #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+               /* locate the ORC unwind tables */
+               if (!strcmp(secstrings + idx, ".orc_unwind_ip")) {
+-                      orc_ip_size = _r(&s->sh_size);
++                      orc_ip_size = _r(&shdr->etype.sh_size);
+                       g_orc_ip_table = (int *)((void *)ehdr +
+-                                                 _r(&s->sh_offset));
++                                                 _r(&shdr->etype.sh_offset));
+               }
+               if (!strcmp(secstrings + idx, ".orc_unwind")) {
+-                      orc_size = _r(&s->sh_size);
++                      orc_size = _r(&shdr->etype.sh_size);
+                       g_orc_table = (struct orc_entry *)((void *)ehdr +
+-                                                           _r(&s->sh_offset));
++                                                           _r(&shdr->etype.sh_offset));
+               }
+ #endif
+       } /* for loop */
+@@ -355,22 +362,22 @@ static int do_sort(Elf_Ehdr *ehdr,
+               goto out;
+       }
+-      extab_image = (void *)ehdr + _r(&extab_sec->sh_offset);
+-      strtab = (const char *)ehdr + _r(&strtab_sec->sh_offset);
++      extab_image = (void *)ehdr + _r(&extab_sec->etype.sh_offset);
++      strtab = (const char *)ehdr + _r(&strtab_sec->etype.sh_offset);
+       symtab = (const Elf_Sym *)((const char *)ehdr +
+-                                                _r(&symtab_sec->sh_offset));
++                                                _r(&symtab_sec->etype.sh_offset));
+       if (custom_sort) {
+-              custom_sort(extab_image, _r(&extab_sec->sh_size));
++              custom_sort(extab_image, _r(&extab_sec->etype.sh_size));
+       } else {
+-              int num_entries = _r(&extab_sec->sh_size) / extable_ent_size;
++              int num_entries = _r(&extab_sec->etype.sh_size) / extable_ent_size;
+               qsort(extab_image, num_entries,
+                     extable_ent_size, compare_extable);
+       }
+       /* find the flag main_extable_sort_needed */
+-      for (sym = (void *)ehdr + _r(&symtab_sec->sh_offset);
+-           sym < sym + _r(&symtab_sec->sh_size) / sizeof(Elf_Sym);
++      for (sym = (void *)ehdr + _r(&symtab_sec->etype.sh_offset);
++           sym < sym + _r(&symtab_sec->etype.sh_size) / sizeof(Elf_Sym);
+            sym++) {
+               if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
+                       continue;
+@@ -388,13 +395,14 @@ static int do_sort(Elf_Ehdr *ehdr,
+               goto out;
+       }
+-      sort_needed_sec = &shdr[get_secindex(r2(&sym->st_shndx),
+-                                           sort_needed_sym - symtab,
+-                                           symtab_shndx)];
++      sort_need_index = get_secindex(r2(&sym->st_shndx),
++                                     sort_needed_sym - symtab,
++                                     symtab_shndx);
++      sort_needed_sec = get_index(shdr_start, shentsize, sort_need_index);
+       sort_needed_loc = (void *)ehdr +
+-              _r(&sort_needed_sec->sh_offset) +
++              _r(&sort_needed_sec->etype.sh_offset) +
+               _r(&sort_needed_sym->st_value) -
+-              _r(&sort_needed_sec->sh_addr);
++              _r(&sort_needed_sec->etype.sh_addr);
+       /* extable has been sorted, clear the flag */
+       w(0, sort_needed_loc);
diff --git a/queue-6.12/scripts-sorttable-use-a-structure-of-function-pointers-for-elf-helpers.patch b/queue-6.12/scripts-sorttable-use-a-structure-of-function-pointers-for-elf-helpers.patch
new file mode 100644 (file)
index 0000000..27ff305
--- /dev/null
@@ -0,0 +1,323 @@
+From stable+bounces-267215-greg=kroah.com@vger.kernel.org Thu Jun 18 21:16:21 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:29 -0400
+Subject: scripts/sorttable: Use a structure of function pointers for elf helpers
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <9d973657ac0dc3be317cf635d9d78cca849760f1.1781809954.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 1e5f6771c247b28135307058d2cfe3b0153733dc ]
+
+Instead of having a series of function pointers that gets assigned to the
+Elf64 or Elf32 versions, put them all into a single structure and use
+that. Add the helper function that chooses the structure into the macros
+that build the different versions of the elf functions.
+
+Link: https://lore.kernel.org/all/CAHk-=wiafEyX7UgOeZgvd6fvuByE5WXUPh9599kwOc_d-pdeug@mail.gmail.com/
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Stephen Rothwell <sfr@canb.auug.org.au>
+Link: https://lore.kernel.org/20250110075459.13d4b94c@gandalf.local.home
+Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.c |  175 +++++++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 118 insertions(+), 57 deletions(-)
+
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -85,6 +85,25 @@ static uint64_t (*r8)(const uint64_t *);
+ static void (*w)(uint32_t, uint32_t *);
+ typedef void (*table_sort_t)(char *, int);
++static struct elf_funcs {
++      int (*compare_extable)(const void *a, const void *b);
++      uint64_t (*ehdr_shoff)(Elf_Ehdr *ehdr);
++      uint16_t (*ehdr_shstrndx)(Elf_Ehdr *ehdr);
++      uint16_t (*ehdr_shentsize)(Elf_Ehdr *ehdr);
++      uint16_t (*ehdr_shnum)(Elf_Ehdr *ehdr);
++      uint64_t (*shdr_addr)(Elf_Shdr *shdr);
++      uint64_t (*shdr_offset)(Elf_Shdr *shdr);
++      uint64_t (*shdr_size)(Elf_Shdr *shdr);
++      uint64_t (*shdr_entsize)(Elf_Shdr *shdr);
++      uint32_t (*shdr_link)(Elf_Shdr *shdr);
++      uint32_t (*shdr_name)(Elf_Shdr *shdr);
++      uint32_t (*shdr_type)(Elf_Shdr *shdr);
++      uint8_t (*sym_type)(Elf_Sym *sym);
++      uint32_t (*sym_name)(Elf_Sym *sym);
++      uint64_t (*sym_value)(Elf_Sym *sym);
++      uint16_t (*sym_shndx)(Elf_Sym *sym);
++} e;
++
+ static uint64_t ehdr64_shoff(Elf_Ehdr *ehdr)
+ {
+       return r8(&ehdr->e64.e_shoff);
+@@ -95,6 +114,11 @@ static uint64_t ehdr32_shoff(Elf_Ehdr *e
+       return r(&ehdr->e32.e_shoff);
+ }
++static uint64_t ehdr_shoff(Elf_Ehdr *ehdr)
++{
++      return e.ehdr_shoff(ehdr);
++}
++
+ #define EHDR_HALF(fn_name)                            \
+ static uint16_t ehdr64_##fn_name(Elf_Ehdr *ehdr)      \
+ {                                                     \
+@@ -104,6 +128,11 @@ static uint16_t ehdr64_##fn_name(Elf_Ehd
+ static uint16_t ehdr32_##fn_name(Elf_Ehdr *ehdr)      \
+ {                                                     \
+       return r2(&ehdr->e32.e_##fn_name);              \
++}                                                     \
++                                                      \
++static uint16_t ehdr_##fn_name(Elf_Ehdr *ehdr)                \
++{                                                     \
++      return e.ehdr_##fn_name(ehdr);                  \
+ }
+ EHDR_HALF(shentsize)
+@@ -119,6 +148,11 @@ static uint32_t shdr64_##fn_name(Elf_Shd
+ static uint32_t shdr32_##fn_name(Elf_Shdr *shdr)      \
+ {                                                     \
+       return r(&shdr->e32.sh_##fn_name);              \
++}                                                     \
++                                                      \
++static uint32_t shdr_##fn_name(Elf_Shdr *shdr)                \
++{                                                     \
++      return e.shdr_##fn_name(shdr);                  \
+ }
+ #define SHDR_ADDR(fn_name)                            \
+@@ -130,6 +164,11 @@ static uint64_t shdr64_##fn_name(Elf_Shd
+ static uint64_t shdr32_##fn_name(Elf_Shdr *shdr)      \
+ {                                                     \
+       return r(&shdr->e32.sh_##fn_name);              \
++}                                                     \
++                                                      \
++static uint64_t shdr_##fn_name(Elf_Shdr *shdr)                \
++{                                                     \
++      return e.shdr_##fn_name(shdr);                  \
+ }
+ #define SHDR_WORD(fn_name)                            \
+@@ -141,6 +180,10 @@ static uint32_t shdr64_##fn_name(Elf_Shd
+ static uint32_t shdr32_##fn_name(Elf_Shdr *shdr)      \
+ {                                                     \
+       return r(&shdr->e32.sh_##fn_name);              \
++}                                                     \
++static uint32_t shdr_##fn_name(Elf_Shdr *shdr)                \
++{                                                     \
++      return e.shdr_##fn_name(shdr);                  \
+ }
+ SHDR_ADDR(addr)
+@@ -161,6 +204,11 @@ static uint64_t sym64_##fn_name(Elf_Sym
+ static uint64_t sym32_##fn_name(Elf_Sym *sym) \
+ {                                             \
+       return r(&sym->e32.st_##fn_name);       \
++}                                             \
++                                              \
++static uint64_t sym_##fn_name(Elf_Sym *sym)   \
++{                                             \
++      return e.sym_##fn_name(sym);            \
+ }
+ #define SYM_WORD(fn_name)                     \
+@@ -172,6 +220,11 @@ static uint32_t sym64_##fn_name(Elf_Sym
+ static uint32_t sym32_##fn_name(Elf_Sym *sym) \
+ {                                             \
+       return r(&sym->e32.st_##fn_name);       \
++}                                             \
++                                              \
++static uint32_t sym_##fn_name(Elf_Sym *sym)   \
++{                                             \
++      return e.sym_##fn_name(sym);            \
+ }
+ #define SYM_HALF(fn_name)                     \
+@@ -183,6 +236,11 @@ static uint16_t sym64_##fn_name(Elf_Sym
+ static uint16_t sym32_##fn_name(Elf_Sym *sym) \
+ {                                             \
+       return r2(&sym->e32.st_##fn_name);      \
++}                                             \
++                                              \
++static uint16_t sym_##fn_name(Elf_Sym *sym)   \
++{                                             \
++      return e.sym_##fn_name(sym);            \
+ }
+ static uint8_t sym64_type(Elf_Sym *sym)
+@@ -195,6 +253,11 @@ static uint8_t sym32_type(Elf_Sym *sym)
+       return ELF32_ST_TYPE(sym->e32.st_info);
+ }
++static uint8_t sym_type(Elf_Sym *sym)
++{
++      return e.sym_type(sym);
++}
++
+ SYM_ADDR(value)
+ SYM_WORD(name)
+ SYM_HALF(shndx)
+@@ -322,29 +385,16 @@ static int compare_extable_64(const void
+       return av > bv;
+ }
++static int compare_extable(const void *a, const void *b)
++{
++      return e.compare_extable(a, b);
++}
++
+ static inline void *get_index(void *start, int entsize, int index)
+ {
+       return start + (entsize * index);
+ }
+-
+-static int (*compare_extable)(const void *a, const void *b);
+-static uint64_t (*ehdr_shoff)(Elf_Ehdr *ehdr);
+-static uint16_t (*ehdr_shstrndx)(Elf_Ehdr *ehdr);
+-static uint16_t (*ehdr_shentsize)(Elf_Ehdr *ehdr);
+-static uint16_t (*ehdr_shnum)(Elf_Ehdr *ehdr);
+-static uint64_t (*shdr_addr)(Elf_Shdr *shdr);
+-static uint64_t (*shdr_offset)(Elf_Shdr *shdr);
+-static uint64_t (*shdr_size)(Elf_Shdr *shdr);
+-static uint64_t (*shdr_entsize)(Elf_Shdr *shdr);
+-static uint32_t (*shdr_link)(Elf_Shdr *shdr);
+-static uint32_t (*shdr_name)(Elf_Shdr *shdr);
+-static uint32_t (*shdr_type)(Elf_Shdr *shdr);
+-static uint8_t (*sym_type)(Elf_Sym *sym);
+-static uint32_t (*sym_name)(Elf_Sym *sym);
+-static uint64_t (*sym_value)(Elf_Sym *sym);
+-static uint16_t (*sym_shndx)(Elf_Sym *sym);
+-
+ static int extable_ent_size;
+ static int long_size;
+@@ -864,7 +914,30 @@ static int do_file(char const *const fna
+       }
+       switch (ehdr->e32.e_ident[EI_CLASS]) {
+-      case ELFCLASS32:
++      case ELFCLASS32: {
++              struct elf_funcs efuncs = {
++                      .compare_extable        = compare_extable_32,
++                      .ehdr_shoff             = ehdr32_shoff,
++                      .ehdr_shentsize         = ehdr32_shentsize,
++                      .ehdr_shstrndx          = ehdr32_shstrndx,
++                      .ehdr_shnum             = ehdr32_shnum,
++                      .shdr_addr              = shdr32_addr,
++                      .shdr_offset            = shdr32_offset,
++                      .shdr_link              = shdr32_link,
++                      .shdr_size              = shdr32_size,
++                      .shdr_name              = shdr32_name,
++                      .shdr_type              = shdr32_type,
++                      .shdr_entsize           = shdr32_entsize,
++                      .sym_type               = sym32_type,
++                      .sym_name               = sym32_name,
++                      .sym_value              = sym32_value,
++                      .sym_shndx              = sym32_shndx,
++              };
++
++              e = efuncs;
++              long_size               = 4;
++              extable_ent_size        = 8;
++
+               if (r2(&ehdr->e32.e_ehsize) != sizeof(Elf32_Ehdr) ||
+                   r2(&ehdr->e32.e_shentsize) != sizeof(Elf32_Shdr)) {
+                       fprintf(stderr,
+@@ -872,26 +945,32 @@ static int do_file(char const *const fna
+                       return -1;
+               }
+-              compare_extable         = compare_extable_32;
+-              ehdr_shoff              = ehdr32_shoff;
+-              ehdr_shentsize          = ehdr32_shentsize;
+-              ehdr_shstrndx           = ehdr32_shstrndx;
+-              ehdr_shnum              = ehdr32_shnum;
+-              shdr_addr               = shdr32_addr;
+-              shdr_offset             = shdr32_offset;
+-              shdr_link               = shdr32_link;
+-              shdr_size               = shdr32_size;
+-              shdr_name               = shdr32_name;
+-              shdr_type               = shdr32_type;
+-              shdr_entsize            = shdr32_entsize;
+-              sym_type                = sym32_type;
+-              sym_name                = sym32_name;
+-              sym_value               = sym32_value;
+-              sym_shndx               = sym32_shndx;
+-              long_size               = 4;
+-              extable_ent_size        = 8;
++              }
+               break;
+-      case ELFCLASS64:
++      case ELFCLASS64: {
++              struct elf_funcs efuncs = {
++                      .compare_extable        = compare_extable_64,
++                      .ehdr_shoff             = ehdr64_shoff,
++                      .ehdr_shentsize         = ehdr64_shentsize,
++                      .ehdr_shstrndx          = ehdr64_shstrndx,
++                      .ehdr_shnum             = ehdr64_shnum,
++                      .shdr_addr              = shdr64_addr,
++                      .shdr_offset            = shdr64_offset,
++                      .shdr_link              = shdr64_link,
++                      .shdr_size              = shdr64_size,
++                      .shdr_name              = shdr64_name,
++                      .shdr_type              = shdr64_type,
++                      .shdr_entsize           = shdr64_entsize,
++                      .sym_type               = sym64_type,
++                      .sym_name               = sym64_name,
++                      .sym_value              = sym64_value,
++                      .sym_shndx              = sym64_shndx,
++              };
++
++              e = efuncs;
++              long_size               = 8;
++              extable_ent_size        = 16;
++
+               if (r2(&ehdr->e64.e_ehsize) != sizeof(Elf64_Ehdr) ||
+                   r2(&ehdr->e64.e_shentsize) != sizeof(Elf64_Shdr)) {
+                       fprintf(stderr,
+@@ -900,25 +979,7 @@ static int do_file(char const *const fna
+                       return -1;
+               }
+-              compare_extable         = compare_extable_64;
+-              ehdr_shoff              = ehdr64_shoff;
+-              ehdr_shentsize          = ehdr64_shentsize;
+-              ehdr_shstrndx           = ehdr64_shstrndx;
+-              ehdr_shnum              = ehdr64_shnum;
+-              shdr_addr               = shdr64_addr;
+-              shdr_offset             = shdr64_offset;
+-              shdr_link               = shdr64_link;
+-              shdr_size               = shdr64_size;
+-              shdr_name               = shdr64_name;
+-              shdr_type               = shdr64_type;
+-              shdr_entsize            = shdr64_entsize;
+-              sym_type                = sym64_type;
+-              sym_name                = sym64_name;
+-              sym_value               = sym64_value;
+-              sym_shndx               = sym64_shndx;
+-              long_size               = 8;
+-              extable_ent_size        = 16;
+-
++              }
+               break;
+       default:
+               fprintf(stderr, "unrecognized ELF class %d %s\n",
diff --git a/queue-6.12/scripts-sorttable-use-normal-sort-if-theres-no-relocs-in-the-mcount-section.patch b/queue-6.12/scripts-sorttable-use-normal-sort-if-theres-no-relocs-in-the-mcount-section.patch
new file mode 100644 (file)
index 0000000..970420d
--- /dev/null
@@ -0,0 +1,63 @@
+From stable+bounces-267225-greg=kroah.com@vger.kernel.org Thu Jun 18 21:17:50 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:39 -0400
+Subject: scripts/sorttable: Use normal sort if theres no relocs in the mcount section
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <d99230ce57a655ac9f9478d03717763f9c16b896.1781809985.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 46514b3c2c17c67cefe84b0c1a59e0aaf6093131 ]
+
+When ARM 64 is compiled with gcc, the mcount_loc section will be filled
+with zeros and the addresses will be located in the Elf_Rela sections. To
+sort the mcount_loc section, the addresses from the Elf_Rela need to be
+placed into an array and that is sorted.
+
+But when ARM 64 is compiled with clang, it does it the same way as other
+architectures and leaves the addresses as is in the mcount_loc section.
+
+To handle both cases, ARM 64 will first try to sort the Elf_Rela section,
+and if it doesn't find any functions, it will then fall back to the
+sorting of the addresses in the mcount_loc section itself.
+
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/20250225182054.648398403@goodmis.org
+Fixes: b3d09d06e052 ("arm64: scripts/sorttable: Implement sorting mcount_loc at boot for arm64")
+Reported-by: "Arnd Bergmann" <arnd@arndb.de>
+Tested-by: Nathan Chancellor <nathan@kernel.org>
+Closes: https://lore.kernel.org/all/893cd8f1-8585-4d25-bf0f-4197bf872465@app.fastmail.com/
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.c |    9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -827,9 +827,14 @@ static void *sort_mcount_loc(void *arg)
+               pthread_exit(m_err);
+       }
+-      if (sort_reloc)
++      if (sort_reloc) {
+               count = fill_relocs(vals, size, ehdr, emloc->start_mcount_loc);
+-      else
++              /* gcc may use relocs to save the addresses, but clang does not. */
++              if (!count) {
++                      count = fill_addrs(vals, size, start_loc);
++                      sort_reloc = 0;
++              }
++      } else
+               count = fill_addrs(vals, size, start_loc);
+       if (count < 0) {
diff --git a/queue-6.12/scripts-sorttable-use-uint64_t-for-mcount-sorting.patch b/queue-6.12/scripts-sorttable-use-uint64_t-for-mcount-sorting.patch
new file mode 100644 (file)
index 0000000..5a65e4e
--- /dev/null
@@ -0,0 +1,137 @@
+From stable+bounces-267212-greg=kroah.com@vger.kernel.org Thu Jun 18 21:16:14 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:26 -0400
+Subject: scripts/sorttable: Use uint64_t for mcount sorting
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <e6b5f67222359383911a6f5e6b28cd192cb6a18a.1781809947.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit 1b649e6ab8dc9188d82c64069493afe66ca0edad ]
+
+The mcount sorting defines uint_t to uint64_t on 64bit architectures and
+uint32_t on 32bit architectures. It can work with just using uint64_t as
+that will hold the values of both, and they are not used to point into the
+ELF file.
+
+sizeof(uint_t) is used for defining the size of the mcount_loc section.
+Instead of using a type, define long_size and use that instead. This will
+allow the header code to be moved into the C file as generic functions and
+not need to include sorttable.h twice, once for 64bit and once for 32bit.
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Link: https://lore.kernel.org/20250105162346.373528925@goodmis.org
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/sorttable.h |   22 +++++++++++-----------
+ 1 file changed, 11 insertions(+), 11 deletions(-)
+
+--- a/scripts/sorttable.h
++++ b/scripts/sorttable.h
+@@ -23,7 +23,6 @@
+ #undef sort_mcount_loc
+ #undef elf_mcount_loc
+ #undef do_sort
+-#undef uint_t
+ #undef ehdr_shoff
+ #undef ehdr_shentsize
+ #undef ehdr_shstrndx
+@@ -39,6 +38,7 @@
+ #undef sym_name
+ #undef sym_value
+ #undef sym_shndx
++#undef long_size
+ #ifdef SORTTABLE_64
+ # define extable_ent_size     16
+@@ -47,7 +47,6 @@
+ # define sort_mcount_loc      sort_mcount_loc_64
+ # define elf_mcount_loc               elf_mcount_loc_64
+ # define do_sort              do_sort_64
+-# define uint_t                       uint64_t
+ # define ehdr_shoff           ehdr64_shoff
+ # define ehdr_shentsize               ehdr64_shentsize
+ # define ehdr_shstrndx                ehdr64_shstrndx
+@@ -63,6 +62,7 @@
+ # define sym_name             sym64_name
+ # define sym_value            sym64_value
+ # define sym_shndx            sym64_shndx
++# define long_size            8
+ #else
+ # define extable_ent_size     8
+ # define compare_extable      compare_extable_32
+@@ -70,7 +70,6 @@
+ # define sort_mcount_loc      sort_mcount_loc_32
+ # define elf_mcount_loc               elf_mcount_loc_32
+ # define do_sort              do_sort_32
+-# define uint_t                       uint32_t
+ # define ehdr_shoff           ehdr32_shoff
+ # define ehdr_shentsize               ehdr32_shentsize
+ # define ehdr_shstrndx                ehdr32_shstrndx
+@@ -86,6 +85,7 @@
+ # define sym_name             sym32_name
+ # define sym_value            sym32_value
+ # define sym_shndx            sym32_shndx
++# define long_size            4
+ #endif
+ #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+@@ -193,25 +193,25 @@ pthread_t mcount_sort_thread;
+ struct elf_mcount_loc {
+       Elf_Ehdr *ehdr;
+       Elf_Shdr *init_data_sec;
+-      uint_t start_mcount_loc;
+-      uint_t stop_mcount_loc;
++      uint64_t start_mcount_loc;
++      uint64_t stop_mcount_loc;
+ };
+ /* Sort the addresses stored between __start_mcount_loc to __stop_mcount_loc in vmlinux */
+ static void *sort_mcount_loc(void *arg)
+ {
+       struct elf_mcount_loc *emloc = (struct elf_mcount_loc *)arg;
+-      uint_t offset = emloc->start_mcount_loc - shdr_addr(emloc->init_data_sec)
++      uint64_t offset = emloc->start_mcount_loc - shdr_addr(emloc->init_data_sec)
+                                       + shdr_offset(emloc->init_data_sec);
+-      uint_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc;
++      uint64_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc;
+       unsigned char *start_loc = (void *)emloc->ehdr + offset;
+-      qsort(start_loc, count/sizeof(uint_t), sizeof(uint_t), compare_extable);
++      qsort(start_loc, count/long_size, long_size, compare_extable);
+       return NULL;
+ }
+ /* Get the address of __start_mcount_loc and __stop_mcount_loc in System.map */
+-static void get_mcount_loc(uint_t *_start, uint_t *_stop)
++static void get_mcount_loc(uint64_t *_start, uint64_t *_stop)
+ {
+       FILE *file_start, *file_stop;
+       char start_buff[20];
+@@ -277,8 +277,8 @@ static int do_sort(Elf_Ehdr *ehdr,
+       unsigned int shstrndx;
+ #ifdef MCOUNT_SORT_ENABLED
+       struct elf_mcount_loc mstruct = {0};
+-      uint_t _start_mcount_loc = 0;
+-      uint_t _stop_mcount_loc = 0;
++      uint64_t _start_mcount_loc = 0;
++      uint64_t _stop_mcount_loc = 0;
+ #endif
+ #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+       unsigned int orc_ip_size = 0;
diff --git a/queue-6.12/scripts-sorttable-zero-out-weak-functions-in-mcount_loc-table.patch b/queue-6.12/scripts-sorttable-zero-out-weak-functions-in-mcount_loc-table.patch
new file mode 100644 (file)
index 0000000..33ccd62
--- /dev/null
@@ -0,0 +1,310 @@
+From stable+bounces-267219-greg=kroah.com@vger.kernel.org Thu Jun 18 21:17:01 2026
+From: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Date: Thu, 18 Jun 2026 16:15:33 -0400
+Subject: scripts/sorttable: Zero out weak functions in mcount_loc table
+To: <stable@vger.kernel.org>
+Cc: <gregkh@linuxfoundation.org>, <sashal@kernel.org>, <rostedt@goodmis.org>, <vmalik@redhat.com>, <jmarchan@redhat.com>, <martin.kelly@crowdstrike.com>, <justin.deschamp@crowdstrike.com>, <linux-open-source@crowdstrike.com>
+Message-ID: <ec4eda957478678f39fc5cfe27a29ab345e1bb51.1781809966.git.andrey.grodzovsky@crowdstrike.com>
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit ef378c3b8233855497a414b9d67bf22592c928a4 ]
+
+When a function is annotated as "weak" and is overridden, the code is not
+removed. If it is traced, the fentry/mcount location in the weak function
+will be referenced by the "__mcount_loc" section. This will then be added
+to the available_filter_functions list. Since only the address of the
+functions are listed, to find the name to show, a search of kallsyms is
+used.
+
+Since kallsyms will return the function by simply finding the function
+that the address is after but before the next function, an address of a
+weak function will show up as the function before it. This is because
+kallsyms does not save names of weak functions. This has caused issues in
+the past, as now the traced weak function will be listed in
+available_filter_functions with the name of the function before it.
+
+At best, this will cause the previous function's name to be listed twice.
+At worse, if the previous function was marked notrace, it will now show up
+as a function that can be traced. Note that it only shows up that it can
+be traced but will not be if enabled, which causes confusion.
+
+ https://lore.kernel.org/all/20220412094923.0abe90955e5db486b7bca279@kernel.org/
+
+The commit b39181f7c6907 ("ftrace: Add FTRACE_MCOUNT_MAX_OFFSET to avoid
+adding weak function") was a workaround to this by checking the function
+address before printing its name. If the address was too far from the
+function given by the name then instead of printing the name it would
+print: __ftrace_invalid_address___<invalid-offset>
+
+The real issue is that these invalid addresses are listed in the ftrace
+table look up which available_filter_functions is derived from. A place
+holder must be listed in that file because set_ftrace_filter may take a
+series of indexes into that file instead of names to be able to do O(1)
+lookups to enable filtering (many tools use this method).
+
+Even if kallsyms saved the size of the function, it does not remove the
+need of having these place holders. The real solution is to not add a weak
+function into the ftrace table in the first place.
+
+To solve this, the sorttable.c code that sorts the mcount regions during
+the build is modified to take a "nm -S vmlinux" input, sort it, and any
+function listed in the mcount_loc section that is not within a boundary of
+the function list given by nm is considered a weak function and is zeroed
+out.
+
+Note, this does not mean they will remain zero when booting as KASLR
+will still shift those addresses. To handle this, the entries in the
+mcount_loc section will be ignored if they are zero or match the
+kaslr_offset() value.
+
+Before:
+
+ ~# grep __ftrace_invalid_address___ /sys/kernel/tracing/available_filter_functions | wc -l
+ 551
+
+After:
+
+ ~# grep __ftrace_invalid_address___ /sys/kernel/tracing/available_filter_functions | wc -l
+ 0
+
+Cc: bpf <bpf@vger.kernel.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: Martin  Kelly <martin.kelly@crowdstrike.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Heiko Carstens <hca@linux.ibm.com>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: Vasily Gorbik <gor@linux.ibm.com>
+Cc: Alexander Gordeev <agordeev@linux.ibm.com>
+Link: https://lore.kernel.org/20250218200022.883095980@goodmis.org
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/ftrace.c   |    6 +-
+ scripts/link-vmlinux.sh |    4 +
+ scripts/sorttable.c     |  128 +++++++++++++++++++++++++++++++++++++++++++++++-
+ 3 files changed, 134 insertions(+), 4 deletions(-)
+
+--- a/kernel/trace/ftrace.c
++++ b/kernel/trace/ftrace.c
+@@ -7048,6 +7048,7 @@ static int ftrace_process_locs(struct mo
+       unsigned long count;
+       unsigned long *p;
+       unsigned long addr;
++      unsigned long kaslr;
+       unsigned long flags = 0; /* Shut up gcc */
+       int ret = -ENOMEM;
+@@ -7096,6 +7097,9 @@ static int ftrace_process_locs(struct mo
+               ftrace_pages->next = start_pg;
+       }
++      /* For zeroed locations that were shifted for core kernel */
++      kaslr = !mod ? kaslr_offset() : 0;
++
+       p = start;
+       pg = start_pg;
+       while (p < end) {
+@@ -7107,7 +7111,7 @@ static int ftrace_process_locs(struct mo
+                * object files to satisfy alignments.
+                * Skip any NULL pointers.
+                */
+-              if (!addr) {
++              if (!addr || addr == kaslr) {
+                       skipped++;
+                       continue;
+               }
+--- a/scripts/link-vmlinux.sh
++++ b/scripts/link-vmlinux.sh
+@@ -173,12 +173,14 @@ mksysmap()
+ sorttable()
+ {
+-      ${objtree}/scripts/sorttable ${1}
++      ${NM} -S ${1} > .tmp_vmlinux.nm-sort
++      ${objtree}/scripts/sorttable -s .tmp_vmlinux.nm-sort ${1}
+ }
+ cleanup()
+ {
+       rm -f .btf.*
++      rm -f .tmp_vmlinux.nm-sort
+       rm -f System.map
+       rm -f vmlinux
+       rm -f vmlinux.map
+--- a/scripts/sorttable.c
++++ b/scripts/sorttable.c
+@@ -580,6 +580,98 @@ static void rela_write_addend(Elf_Rela *
+       e.rela_write_addend(rela, val);
+ }
++struct func_info {
++      uint64_t        addr;
++      uint64_t        size;
++};
++
++/* List of functions created by: nm -S vmlinux */
++static struct func_info *function_list;
++static int function_list_size;
++
++/* Allocate functions in 1k blocks */
++#define FUNC_BLK_SIZE 1024
++#define FUNC_BLK_MASK (FUNC_BLK_SIZE - 1)
++
++static int add_field(uint64_t addr, uint64_t size)
++{
++      struct func_info *fi;
++      int fsize = function_list_size;
++
++      if (!(fsize & FUNC_BLK_MASK)) {
++              fsize += FUNC_BLK_SIZE;
++              fi = realloc(function_list, fsize * sizeof(struct func_info));
++              if (!fi)
++                      return -1;
++              function_list = fi;
++      }
++      fi = &function_list[function_list_size++];
++      fi->addr = addr;
++      fi->size = size;
++      return 0;
++}
++
++/* Only return match if the address lies inside the function size */
++static int cmp_func_addr(const void *K, const void *A)
++{
++      uint64_t key = *(const uint64_t *)K;
++      const struct func_info *a = A;
++
++      if (key < a->addr)
++              return -1;
++      return key >= a->addr + a->size;
++}
++
++/* Find the function in function list that is bounded by the function size */
++static int find_func(uint64_t key)
++{
++      return bsearch(&key, function_list, function_list_size,
++                     sizeof(struct func_info), cmp_func_addr) != NULL;
++}
++
++static int cmp_funcs(const void *A, const void *B)
++{
++      const struct func_info *a = A;
++      const struct func_info *b = B;
++
++      if (a->addr < b->addr)
++              return -1;
++      return a->addr > b->addr;
++}
++
++static int parse_symbols(const char *fname)
++{
++      FILE *fp;
++      char addr_str[20]; /* Only need 17, but round up to next int size */
++      char size_str[20];
++      char type;
++
++      fp = fopen(fname, "r");
++      if (!fp) {
++              perror(fname);
++              return -1;
++      }
++
++      while (fscanf(fp, "%16s %16s %c %*s\n", addr_str, size_str, &type) == 3) {
++              uint64_t addr;
++              uint64_t size;
++
++              /* Only care about functions */
++              if (type != 't' && type != 'T' && type != 'W')
++                      continue;
++
++              addr = strtoull(addr_str, NULL, 16);
++              size = strtoull(size_str, NULL, 16);
++              if (add_field(addr, size) < 0)
++                      return -1;
++      }
++      fclose(fp);
++
++      qsort(function_list, function_list_size, sizeof(struct func_info), cmp_funcs);
++
++      return 0;
++}
++
+ static pthread_t mcount_sort_thread;
+ static bool sort_reloc;
+@@ -752,6 +844,21 @@ static void *sort_mcount_loc(void *arg)
+               goto out;
+       }
++      /* zero out any locations not found by function list */
++      if (function_list_size) {
++              for (void *ptr = vals; ptr < vals + size; ptr += long_size) {
++                      uint64_t key;
++
++                      key = long_size == 4 ? r((uint32_t *)ptr) : r8((uint64_t *)ptr);
++                      if (!find_func(key)) {
++                              if (long_size == 4)
++                                      *(uint32_t *)ptr = 0;
++                              else
++                                      *(uint64_t *)ptr = 0;
++                      }
++              }
++      }
++
+       compare_values = long_size == 4 ? compare_values_32 : compare_values_64;
+       qsort(vals, count, long_size, compare_values);
+@@ -801,6 +908,8 @@ static void get_mcount_loc(struct elf_mc
+               return;
+       }
+ }
++#else /* MCOUNT_SORT_ENABLED */
++static inline int parse_symbols(const char *fname) { return 0; }
+ #endif
+ static int do_sort(Elf_Ehdr *ehdr,
+@@ -1256,14 +1365,29 @@ int main(int argc, char *argv[])
+       int i, n_error = 0;  /* gcc-4.3.0 false positive complaint */
+       size_t size = 0;
+       void *addr = NULL;
++      int c;
++
++      while ((c = getopt(argc, argv, "s:")) >= 0) {
++              switch (c) {
++              case 's':
++                      if (parse_symbols(optarg) < 0) {
++                              fprintf(stderr, "Could not parse %s\n", optarg);
++                              return -1;
++                      }
++                      break;
++              default:
++                      fprintf(stderr, "usage: sorttable [-s nm-file] vmlinux...\n");
++                      return 0;
++              }
++      }
+-      if (argc < 2) {
++      if ((argc - optind) < 1) {
+               fprintf(stderr, "usage: sorttable vmlinux...\n");
+               return 0;
+       }
+       /* Process each file in turn, allowing deep failure. */
+-      for (i = 1; i < argc; i++) {
++      for (i = optind; i < argc; i++) {
+               addr = mmap_file(argv[i], &size);
+               if (!addr) {
+                       ++n_error;
diff --git a/queue-6.12/sctp-disable-bh-before-calling-udp_tunnel_xmit_skb.patch b/queue-6.12/sctp-disable-bh-before-calling-udp_tunnel_xmit_skb.patch
new file mode 100644 (file)
index 0000000..891bf2f
--- /dev/null
@@ -0,0 +1,89 @@
+From stable+bounces-268303-greg=kroah.com@vger.kernel.org Thu Jun 25 09:25:37 2026
+From: Alexander Martyniuk <alexevgmart@gmail.com>
+Date: Thu, 25 Jun 2026 11:24:42 +0300
+Subject: sctp: disable BH before calling udp_tunnel_xmit_skb()
+To: stable@vger.kernel.org, gregkh@linuxfoundation.org
+Cc: Alexander Martyniuk <alexevgmart@gmail.com>, Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>, Xin Long <lucien.xin@gmail.com>, "David S. Miller" <davem@davemloft.net>, Eric Dumazet <edumazet@google.com>, Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>, Weiming Shi <bestswngs@gmail.com>, linux-sctp@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org
+Message-ID: <20260625082442.96390-3-alexevgmart@gmail.com>
+
+From: Xin Long <lucien.xin@gmail.com>
+
+commit 2cd7e6971fc2787408ceef17906ea152791448cf upstream.
+
+udp_tunnel_xmit_skb() / udp_tunnel6_xmit_skb() are expected to run with
+BH disabled.  After commit 6f1a9140ecda ("add xmit recursion limit to
+tunnel xmit functions"), on the path:
+
+  udp(6)_tunnel_xmit_skb() -> ip(6)tunnel_xmit()
+
+dev_xmit_recursion_inc()/dec() must stay balanced on the same CPU.
+
+Without local_bh_disable(), the context may move between CPUs, which can
+break the inc/dec pairing. This may lead to incorrect recursion level
+detection and cause packets to be dropped in ip(6)_tunnel_xmit() or
+__dev_queue_xmit().
+
+Fix it by disabling BH around both IPv4 and IPv6 SCTP UDP xmit paths.
+
+In my testing, after enabling the SCTP over UDP:
+
+  # ip net exec ha sysctl -w net.sctp.udp_port=9899
+  # ip net exec ha sysctl -w net.sctp.encap_port=9899
+  # ip net exec hb sysctl -w net.sctp.udp_port=9899
+  # ip net exec hb sysctl -w net.sctp.encap_port=9899
+
+  # ip net exec ha iperf3 -s
+
+- without this patch:
+
+  # ip net exec hb iperf3 -c 192.168.0.1 --sctp
+  [  5]   0.00-10.00  sec  37.2 MBytes  31.2 Mbits/sec  sender
+  [  5]   0.00-10.00  sec  37.1 MBytes  31.1 Mbits/sec  receiver
+
+- with this patch:
+
+  # ip net exec hb iperf3 -c 192.168.0.1 --sctp
+  [  5]   0.00-10.00  sec  3.14 GBytes  2.69 Gbits/sec  sender
+  [  5]   0.00-10.00  sec  3.14 GBytes  2.69 Gbits/sec  receiver
+
+Fixes: 6f1a9140ecda ("net: add xmit recursion limit to tunnel xmit functions")
+Fixes: 046c052b475e ("sctp: enable udp tunneling socks")
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Link: https://patch.msgid.link/c874a8548221dcd56ff03c65ba75a74e6cf99119.1776017727.git.lucien.xin@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Alexander Martyniuk <alexevgmart@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/ipv6.c     |    2 ++
+ net/sctp/protocol.c |    2 ++
+ 2 files changed, 4 insertions(+)
+
+--- a/net/sctp/ipv6.c
++++ b/net/sctp/ipv6.c
+@@ -261,9 +261,11 @@ static int sctp_v6_xmit(struct sk_buff *
+       skb_set_inner_ipproto(skb, IPPROTO_SCTP);
+       label = ip6_make_flowlabel(sock_net(sk), skb, fl6->flowlabel, true, fl6);
++      local_bh_disable();
+       udp_tunnel6_xmit_skb(dst, sk, skb, NULL, &fl6->saddr, &fl6->daddr,
+                            tclass, ip6_dst_hoplimit(dst), label,
+                            sctp_sk(sk)->udp_port, t->encap_port, false);
++      local_bh_enable();
+       return 0;
+ }
+--- a/net/sctp/protocol.c
++++ b/net/sctp/protocol.c
+@@ -1086,9 +1086,11 @@ static inline int sctp_v4_xmit(struct sk
+       skb_reset_inner_mac_header(skb);
+       skb_reset_inner_transport_header(skb);
+       skb_set_inner_ipproto(skb, IPPROTO_SCTP);
++      local_bh_disable();
+       udp_tunnel_xmit_skb(dst_rtable(dst), sk, skb, fl4->saddr,
+                           fl4->daddr, dscp, ip4_dst_hoplimit(dst), df,
+                           sctp_sk(sk)->udp_port, t->encap_port, false, false);
++      local_bh_enable();
+       return 0;
+ }
index 498c40e6536f7bdc93be7820d2960be80f048407..f075319a59acf8a1230a17049dd136c864722720 100644 (file)
@@ -54,3 +54,32 @@ phonet-pass-net-and-ifindex-to-phonet_address_notify.patch
 net-phonet-free-phonet_device-after-rcu-grace-period.patch
 rxrpc-fix-the-ack-parser-to-extract-the-sack-table-for-parsing.patch
 fuse-re-lock-request-before-replacing-page-cache-folio.patch
+scripts-sorttable-remove-unused-macro-defines.patch
+scripts-sorttable-remove-unused-write-functions.patch
+scripts-sorttable-remove-unneeded-elf_rel.patch
+scripts-sorttable-have-the-orc-code-use-the-_r-functions-to-read.patch
+scripts-sorttable-make-compare_extable-into-two-functions.patch
+scripts-sorttable-convert-elf_ehdr-to-union.patch
+scripts-sorttable-replace-elf_shdr-macro-with-a-union.patch
+scripts-sorttable-convert-elf_sym-macro-over-to-a-union.patch
+scripts-sorttable-add-helper-functions-for-elf_ehdr.patch
+scripts-sorttable-add-helper-functions-for-elf_shdr.patch
+scripts-sorttable-add-helper-functions-for-elf_sym.patch
+scripts-sorttable-use-uint64_t-for-mcount-sorting.patch
+scripts-sorttable-move-code-from-sorttable.h-into-sorttable.c.patch
+scripts-sorttable-get-start-stop_mcount_loc-from-elf-file-directly.patch
+scripts-sorttable-use-a-structure-of-function-pointers-for-elf-helpers.patch
+arm64-scripts-sorttable-implement-sorting-mcount_loc-at-boot-for-arm64.patch
+scripts-sorttable-have-mcount-rela-sort-use-direct-values.patch
+scripts-sorttable-always-use-an-array-for-the-mcount_loc-sorting.patch
+scripts-sorttable-zero-out-weak-functions-in-mcount_loc-table.patch
+ftrace-update-the-mcount_loc-check-of-skipped-entries.patch
+ftrace-have-ftrace-pages-output-reflect-freed-pages.patch
+ftrace-do-not-over-allocate-ftrace-memory.patch
+ftrace-test-mcount_loc-addr-before-calling-ftrace_call_addr.patch
+ftrace-check-against-is_kernel_text-instead-of-kaslr_offset.patch
+scripts-sorttable-use-normal-sort-if-theres-no-relocs-in-the-mcount-section.patch
+scripts-sorttable-allow-matches-to-functions-before-function-entry.patch
+scripts-sorttable-fix-endianness-handling-in-build-time-mcount-sort.patch
+net-ipv6-make-udp_tunnel6_xmit_skb-void.patch
+sctp-disable-bh-before-calling-udp_tunnel_xmit_skb.patch