modbuildid is never set when kallsyms_lookup_buildid is returning via
successful ftrace_mod_address_lookup.

This leads to an uninitialized pointer dereference on x86 when
CONFIG_STACKTRACE_BUILD_ID=y inside __sprint_symbol.

Prevent this by always initializing modbuildid.

Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220717
Signed-off-by: Maurice Hieronymus <[email protected]>
---
 include/linux/ftrace.h | 4 ++--
 kernel/kallsyms.c      | 2 +-
 kernel/trace/ftrace.c  | 8 +++++++-
 3 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 770f0dc993cc..ed673fa2536b 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -87,11 +87,11 @@ struct ftrace_hash;
        defined(CONFIG_DYNAMIC_FTRACE)
 int
 ftrace_mod_address_lookup(unsigned long addr, unsigned long *size,
-                  unsigned long *off, char **modname, char *sym);
+                  unsigned long *off, char **modname, const unsigned char 
**modbuildid, char *sym);
 #else
 static inline int
 ftrace_mod_address_lookup(unsigned long addr, unsigned long *size,
-                  unsigned long *off, char **modname, char *sym)
+                  unsigned long *off, char **modname, const unsigned char 
**modbuildid, char *sym)
 {
        return 0;
 }
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index 049e296f586c..5ca69eafda7a 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -382,7 +382,7 @@ static int kallsyms_lookup_buildid(unsigned long addr,
 
        if (!ret)
                ret = ftrace_mod_address_lookup(addr, symbolsize,
-                                               offset, modname, namebuf);
+                                               offset, modname, modbuildid, 
namebuf);
 
        return ret;
 }
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index ef2d5dca6f70..6eba92a52261 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -7752,7 +7752,7 @@ ftrace_func_address_lookup(struct ftrace_mod_map *mod_map,
 
 int
 ftrace_mod_address_lookup(unsigned long addr, unsigned long *size,
-                  unsigned long *off, char **modname, char *sym)
+                  unsigned long *off, char **modname, const unsigned char 
**modbuildid, char *sym)
 {
        struct ftrace_mod_map *mod_map;
        int ret = 0;
@@ -7764,6 +7764,12 @@ ftrace_mod_address_lookup(unsigned long addr, unsigned 
long *size,
                if (ret) {
                        if (modname)
                                *modname = mod_map->mod->name;
+                       if (modbuildid)
+#ifdef CONFIG_STACKTRACE_BUILD_ID
+                               *modbuildid = mod_map->mod->build_id;
+#else
+                               *modbuildid = NULL;
+#endif
                        break;
                }
        }
-- 
2.50.1


Reply via email to