]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.10
authorSasha Levin <sashal@kernel.org>
Mon, 3 Feb 2025 16:25:51 +0000 (11:25 -0500)
committerSasha Levin <sashal@kernel.org>
Mon, 3 Feb 2025 16:25:51 +0000 (11:25 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.10/genksyms-fix-memory-leak-when-the-same-symbol-is-add.patch [new file with mode: 0644]
queue-5.10/genksyms-fix-memory-leak-when-the-same-symbol-is-rea.patch [new file with mode: 0644]
queue-5.10/hexagon-fix-unbalanced-spinlock-in-die.patch [new file with mode: 0644]
queue-5.10/hexagon-fix-using-plain-integer-as-null-pointer-warn.patch [new file with mode: 0644]
queue-5.10/series

diff --git a/queue-5.10/genksyms-fix-memory-leak-when-the-same-symbol-is-add.patch b/queue-5.10/genksyms-fix-memory-leak-when-the-same-symbol-is-add.patch
new file mode 100644 (file)
index 0000000..fd0ca8e
--- /dev/null
@@ -0,0 +1,149 @@
+From ae0d97c94282b8ba26a8442ad6392d2511876c00 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 Jan 2025 16:30:38 +0900
+Subject: genksyms: fix memory leak when the same symbol is added from source
+
+From: Masahiro Yamada <masahiroy@kernel.org>
+
+[ Upstream commit 45c9c4101d3d2fdfa00852274bbebba65fcc3cf2 ]
+
+When a symbol that is already registered is added again, __add_symbol()
+returns without freeing the symbol definition, making it unreachable.
+
+The following test cases demonstrate different memory leak points.
+
+[Test Case 1]
+
+Forward declaration with exactly the same definition
+
+  $ cat foo.c
+  #include <linux/export.h>
+  void foo(void);
+  void foo(void) {}
+  EXPORT_SYMBOL(foo);
+
+[Test Case 2]
+
+Forward declaration with a different definition (e.g. attribute)
+
+  $ cat foo.c
+  #include <linux/export.h>
+  void foo(void);
+  __attribute__((__section__(".ref.text"))) void foo(void) {}
+  EXPORT_SYMBOL(foo);
+
+[Test Case 3]
+
+Preserving an overridden symbol (compile with KBUILD_PRESERVE=1)
+
+  $ cat foo.c
+  #include <linux/export.h>
+  void foo(void);
+  void foo(void) { }
+  EXPORT_SYMBOL(foo);
+
+  $ cat foo.symref
+  override foo void foo ( int )
+
+The memory leaks in Test Case 1 and 2 have existed since the introduction
+of genksyms into the kernel tree. [1]
+
+The memory leak in Test Case 3 was introduced by commit 5dae9a550a74
+("genksyms: allow to ignore symbol checksum changes").
+
+When multiple init_declarators are reduced to an init_declarator_list,
+the decl_spec must be duplicated. Otherwise, the following Test Case 4
+would result in a double-free bug.
+
+[Test Case 4]
+
+  $ cat foo.c
+  #include <linux/export.h>
+
+  extern int foo, bar;
+
+  int foo, bar;
+  EXPORT_SYMBOL(foo);
+
+In this case, 'foo' and 'bar' share the same decl_spec, 'int'. It must
+be unshared before being passed to add_symbol().
+
+[1]: https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/commit/?id=46bd1da672d66ccd8a639d3c1f8a166048cca608
+
+Fixes: 5dae9a550a74 ("genksyms: allow to ignore symbol checksum changes")
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ scripts/genksyms/genksyms.c |  3 +++
+ scripts/genksyms/parse.y    | 14 ++++++++++++--
+ 2 files changed, 15 insertions(+), 2 deletions(-)
+
+diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
+index 23eff234184f3..d74bad87ef1a7 100644
+--- a/scripts/genksyms/genksyms.c
++++ b/scripts/genksyms/genksyms.c
+@@ -241,6 +241,7 @@ static struct symbol *__add_symbol(const char *name, enum symbol_type type,
+                                               "unchanged\n");
+                               }
+                               sym->is_declared = 1;
++                              free_list(defn, NULL);
+                               return sym;
+                       } else if (!sym->is_declared) {
+                               if (sym->is_override && flag_preserve) {
+@@ -249,6 +250,7 @@ static struct symbol *__add_symbol(const char *name, enum symbol_type type,
+                                       print_type_name(type, name);
+                                       fprintf(stderr, " modversion change\n");
+                                       sym->is_declared = 1;
++                                      free_list(defn, NULL);
+                                       return sym;
+                               } else {
+                                       status = is_unknown_symbol(sym) ?
+@@ -256,6 +258,7 @@ static struct symbol *__add_symbol(const char *name, enum symbol_type type,
+                               }
+                       } else {
+                               error_with_pos("redefinition of %s", name);
++                              free_list(defn, NULL);
+                               return sym;
+                       }
+                       break;
+diff --git a/scripts/genksyms/parse.y b/scripts/genksyms/parse.y
+index e22b42245bcc2..7df3fe290d535 100644
+--- a/scripts/genksyms/parse.y
++++ b/scripts/genksyms/parse.y
+@@ -149,14 +149,19 @@ simple_declaration:
+       ;
+ init_declarator_list_opt:
+-      /* empty */                             { $$ = NULL; }
+-      | init_declarator_list
++      /* empty */                     { $$ = NULL; }
++      | init_declarator_list          { free_list(decl_spec, NULL); $$ = $1; }
+       ;
+ init_declarator_list:
+       init_declarator
+               { struct string_list *decl = *$1;
+                 *$1 = NULL;
++
++                /* avoid sharing among multiple init_declarators */
++                if (decl_spec)
++                  decl_spec = copy_list_range(decl_spec, NULL);
++
+                 add_symbol(current_name,
+                            is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);
+                 current_name = NULL;
+@@ -167,6 +172,11 @@ init_declarator_list:
+                 *$3 = NULL;
+                 free_list(*$2, NULL);
+                 *$2 = decl_spec;
++
++                /* avoid sharing among multiple init_declarators */
++                if (decl_spec)
++                  decl_spec = copy_list_range(decl_spec, NULL);
++
+                 add_symbol(current_name,
+                            is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);
+                 current_name = NULL;
+-- 
+2.39.5
+
diff --git a/queue-5.10/genksyms-fix-memory-leak-when-the-same-symbol-is-rea.patch b/queue-5.10/genksyms-fix-memory-leak-when-the-same-symbol-is-rea.patch
new file mode 100644 (file)
index 0000000..d984141
--- /dev/null
@@ -0,0 +1,108 @@
+From e53d587b7ace881bcbcba3a5785550dbf48f89fd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 Jan 2025 16:30:39 +0900
+Subject: genksyms: fix memory leak when the same symbol is read from *.symref
+ file
+
+From: Masahiro Yamada <masahiroy@kernel.org>
+
+[ Upstream commit be2fa44b5180a1f021efb40c55fdf63c249c3209 ]
+
+When a symbol that is already registered is read again from *.symref
+file, __add_symbol() removes the previous one from the hash table without
+freeing it.
+
+[Test Case]
+
+  $ cat foo.c
+  #include <linux/export.h>
+  void foo(void);
+  void foo(void) {}
+  EXPORT_SYMBOL(foo);
+
+  $ cat foo.symref
+  foo void foo ( void )
+  foo void foo ( void )
+
+When a symbol is removed from the hash table, it must be freed along
+with its ->name and ->defn members. However, sym->name cannot be freed
+because it is sometimes shared with node->string, but not always. If
+sym->name and node->string share the same memory, free(sym->name) could
+lead to a double-free bug.
+
+To resolve this issue, always assign a strdup'ed string to sym->name.
+
+Fixes: 64e6c1e12372 ("genksyms: track symbol checksum changes")
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ scripts/genksyms/genksyms.c | 8 ++++++--
+ scripts/genksyms/genksyms.h | 2 +-
+ scripts/genksyms/parse.y    | 4 ++--
+ 3 files changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
+index d74bad87ef1a7..a87fafbbec268 100644
+--- a/scripts/genksyms/genksyms.c
++++ b/scripts/genksyms/genksyms.c
+@@ -274,11 +274,15 @@ static struct symbol *__add_symbol(const char *name, enum symbol_type type,
+                               break;
+                       }
+               }
++
++              free_list(sym->defn, NULL);
++              free(sym->name);
++              free(sym);
+               --nsyms;
+       }
+       sym = xmalloc(sizeof(*sym));
+-      sym->name = name;
++      sym->name = xstrdup(name);
+       sym->type = type;
+       sym->defn = defn;
+       sym->expansion_trail = NULL;
+@@ -485,7 +489,7 @@ static void read_reference(FILE *f)
+                       defn = def;
+                       def = read_node(f);
+               }
+-              subsym = add_reference_symbol(xstrdup(sym->string), sym->tag,
++              subsym = add_reference_symbol(sym->string, sym->tag,
+                                             defn, is_extern);
+               subsym->is_override = is_override;
+               free_node(sym);
+diff --git a/scripts/genksyms/genksyms.h b/scripts/genksyms/genksyms.h
+index 2bcdb9bebab40..4ead4e0adb821 100644
+--- a/scripts/genksyms/genksyms.h
++++ b/scripts/genksyms/genksyms.h
+@@ -32,7 +32,7 @@ struct string_list {
+ struct symbol {
+       struct symbol *hash_next;
+-      const char *name;
++      char *name;
+       enum symbol_type type;
+       struct string_list *defn;
+       struct symbol *expansion_trail;
+diff --git a/scripts/genksyms/parse.y b/scripts/genksyms/parse.y
+index 7df3fe290d535..84813ce54a2dd 100644
+--- a/scripts/genksyms/parse.y
++++ b/scripts/genksyms/parse.y
+@@ -479,12 +479,12 @@ enumerator_list:
+ enumerator:
+       IDENT
+               {
+-                      const char *name = strdup((*$1)->string);
++                      const char *name = (*$1)->string;
+                       add_symbol(name, SYM_ENUM_CONST, NULL, 0);
+               }
+       | IDENT '=' EXPRESSION_PHRASE
+               {
+-                      const char *name = strdup((*$1)->string);
++                      const char *name = (*$1)->string;
+                       struct string_list *expr = copy_list_range(*$3, *$2);
+                       add_symbol(name, SYM_ENUM_CONST, expr, 0);
+               }
+-- 
+2.39.5
+
diff --git a/queue-5.10/hexagon-fix-unbalanced-spinlock-in-die.patch b/queue-5.10/hexagon-fix-unbalanced-spinlock-in-die.patch
new file mode 100644 (file)
index 0000000..43e64e3
--- /dev/null
@@ -0,0 +1,45 @@
+From 89022055c0f8767abdd0e5736fea7f28231be532 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 May 2023 02:56:08 +0000
+Subject: hexagon: Fix unbalanced spinlock in die()
+
+From: Lin Yujun <linyujun809@huawei.com>
+
+[ Upstream commit 03410e87563a122075c3721acc7d5510e41d8332 ]
+
+die executes holding the spinlock of &die.lock and unlock
+it after printing the oops message.
+However in the code if the notify_die() returns NOTIFY_STOP
+, die() exit with returning 1 but never unlocked the spinlock.
+
+Fix this by adding spin_unlock_irq(&die.lock) before returning.
+
+Fixes: cf9750bae262 ("Hexagon: Provide basic debugging and system trap support.")
+Signed-off-by: Lin Yujun <linyujun809@huawei.com>
+Link: https://lore.kernel.org/r/20230522025608.2515558-1-linyujun809@huawei.com
+Signed-off-by: Brian Cain <bcain@quicinc.com>
+Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/hexagon/kernel/traps.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/arch/hexagon/kernel/traps.c b/arch/hexagon/kernel/traps.c
+index b334e80717099..653328606ef31 100644
+--- a/arch/hexagon/kernel/traps.c
++++ b/arch/hexagon/kernel/traps.c
+@@ -199,8 +199,10 @@ int die(const char *str, struct pt_regs *regs, long err)
+       printk(KERN_EMERG "Oops: %s[#%d]:\n", str, ++die.counter);
+       if (notify_die(DIE_OOPS, str, regs, err, pt_cause(regs), SIGSEGV) ==
+-          NOTIFY_STOP)
++          NOTIFY_STOP) {
++              spin_unlock_irq(&die.lock);
+               return 1;
++      }
+       print_modules();
+       show_regs(regs);
+-- 
+2.39.5
+
diff --git a/queue-5.10/hexagon-fix-using-plain-integer-as-null-pointer-warn.patch b/queue-5.10/hexagon-fix-using-plain-integer-as-null-pointer-warn.patch
new file mode 100644 (file)
index 0000000..f842fb8
--- /dev/null
@@ -0,0 +1,61 @@
+From 4f57b80b5bb933f948feace23e048ad46c39dc83 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 17:17:34 -0500
+Subject: hexagon: fix using plain integer as NULL pointer warning in cmpxchg
+
+From: Willem de Bruijn <willemb@google.com>
+
+[ Upstream commit 8a20030038742b9915c6d811a4e6c14b126cafb4 ]
+
+Sparse reports
+
+    net/ipv4/inet_diag.c:1511:17: sparse: sparse: Using plain integer as NULL pointer
+
+Due to this code calling cmpxchg on a non-integer type
+struct inet_diag_handler *
+
+    return !cmpxchg((const struct inet_diag_handler**)&inet_diag_table[type],
+                    NULL, h) ? 0 : -EEXIST;
+
+While hexagon's cmpxchg assigns an integer value to a variable of this
+type.
+
+    __typeof__(*(ptr)) __oldval = 0;
+
+Update this assignment to cast 0 to the correct type.
+
+The original issue is easily reproduced at head with the below block,
+and is absent after this change.
+
+    make LLVM=1 ARCH=hexagon defconfig
+    make C=1 LLVM=1 ARCH=hexagon net/ipv4/inet_diag.o
+
+Fixes: 99a70aa051d2 ("Hexagon: Add processor and system headers")
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202411091538.PGSTqUBi-lkp@intel.com/
+Signed-off-by: Willem de Bruijn <willemb@google.com>
+Tested-by: Christian Gmeiner <cgmeiner@igalia.com>
+Link: https://lore.kernel.org/r/20241203221736.282020-1-willemdebruijn.kernel@gmail.com
+Signed-off-by: Brian Cain <bcain@quicinc.com>
+Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/hexagon/include/asm/cmpxchg.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/hexagon/include/asm/cmpxchg.h b/arch/hexagon/include/asm/cmpxchg.h
+index 92b8a02e588ac..9c5f07749933e 100644
+--- a/arch/hexagon/include/asm/cmpxchg.h
++++ b/arch/hexagon/include/asm/cmpxchg.h
+@@ -56,7 +56,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+       __typeof__(ptr) __ptr = (ptr);                          \
+       __typeof__(*(ptr)) __old = (old);                       \
+       __typeof__(*(ptr)) __new = (new);                       \
+-      __typeof__(*(ptr)) __oldval = 0;                        \
++      __typeof__(*(ptr)) __oldval = (__typeof__(*(ptr))) 0;   \
+                                                               \
+       asm volatile(                                           \
+               "1:     %0 = memw_locked(%1);\n"                \
+-- 
+2.39.5
+
index d4295c0d5ce1e58a825e86ff2fb92e05a4f95556..6e8cec81bbfcab670eeb54ae76bc242689b1df22 100644 (file)
@@ -123,3 +123,7 @@ vsock-allow-retrying-on-connect-failure.patch
 bgmac-reduce-max-frame-size-to-support-just-mtu-1500.patch
 net-sh_eth-fix-missing-rtnl-lock-in-suspend-resume-p.patch
 net-hsr-fix-fill_frame_info-regression-vs-vlan-packe.patch
+genksyms-fix-memory-leak-when-the-same-symbol-is-add.patch
+genksyms-fix-memory-leak-when-the-same-symbol-is-rea.patch
+hexagon-fix-using-plain-integer-as-null-pointer-warn.patch
+hexagon-fix-unbalanced-spinlock-in-die.patch