]> git.dujemihanovic.xyz Git - linux.git/commitdiff
kallsyms: rework symbol lookup return codes
authorArnd Bergmann <arnd@arndb.de>
Thu, 4 Apr 2024 10:04:54 +0000 (12:04 +0200)
committerArnd Bergmann <arnd@arndb.de>
Thu, 27 Jun 2024 15:43:40 +0000 (17:43 +0200)
Building with W=1 in some configurations produces a false positive
warning for kallsyms:

kernel/kallsyms.c: In function '__sprint_symbol.isra':
kernel/kallsyms.c:503:17: error: 'strcpy' source argument is the same as destination [-Werror=restrict]
  503 |                 strcpy(buffer, name);
      |                 ^~~~~~~~~~~~~~~~~~~~

This originally showed up while building with -O3, but later started
happening in other configurations as well, depending on inlining
decisions. The underlying issue is that the local 'name' variable is
always initialized to the be the same as 'buffer' in the called functions
that fill the buffer, which gcc notices while inlining, though it could
see that the address check always skips the copy.

The calling conventions here are rather unusual, as all of the internal
lookup functions (bpf_address_lookup, ftrace_mod_address_lookup,
ftrace_func_address_lookup, module_address_lookup and
kallsyms_lookup_buildid) already use the provided buffer and either return
the address of that buffer to indicate success, or NULL for failure,
but the callers are written to also expect an arbitrary other buffer
to be returned.

Rework the calling conventions to return the length of the filled buffer
instead of its address, which is simpler and easier to follow as well
as avoiding the warning. Leave only the kallsyms_lookup() calling conventions
unchanged, since that is called from 16 different functions and
adapting this would be a much bigger change.

Link: https://lore.kernel.org/lkml/20200107214042.855757-1-arnd@arndb.de/
Link: https://lore.kernel.org/lkml/20240326130647.7bfb1d92@gandalf.local.home/
Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
Acked-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
include/linux/filter.h
include/linux/ftrace.h
include/linux/module.h
kernel/bpf/core.c
kernel/kallsyms.c
kernel/module/kallsyms.c
kernel/trace/ftrace.c

index 0f12cf01070e34581c6f1a8d519d777304a649d9..5669da513cd7cc0d0e241021755c5ea270bee006 100644 (file)
@@ -1208,18 +1208,18 @@ static inline bool bpf_jit_kallsyms_enabled(void)
        return false;
 }
 
-const char *__bpf_address_lookup(unsigned long addr, unsigned long *size,
+int __bpf_address_lookup(unsigned long addr, unsigned long *size,
                                 unsigned long *off, char *sym);
 bool is_bpf_text_address(unsigned long addr);
 int bpf_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
                    char *sym);
 struct bpf_prog *bpf_prog_ksym_find(unsigned long addr);
 
-static inline const char *
+static inline int
 bpf_address_lookup(unsigned long addr, unsigned long *size,
                   unsigned long *off, char **modname, char *sym)
 {
-       const char *ret = __bpf_address_lookup(addr, size, off, sym);
+       int ret = __bpf_address_lookup(addr, size, off, sym);
 
        if (ret && modname)
                *modname = NULL;
@@ -1263,11 +1263,11 @@ static inline bool bpf_jit_kallsyms_enabled(void)
        return false;
 }
 
-static inline const char *
+static inline int
 __bpf_address_lookup(unsigned long addr, unsigned long *size,
                     unsigned long *off, char *sym)
 {
-       return NULL;
+       return 0;
 }
 
 static inline bool is_bpf_text_address(unsigned long addr)
@@ -1286,11 +1286,11 @@ static inline struct bpf_prog *bpf_prog_ksym_find(unsigned long addr)
        return NULL;
 }
 
-static inline const char *
+static inline int
 bpf_address_lookup(unsigned long addr, unsigned long *size,
                   unsigned long *off, char **modname, char *sym)
 {
-       return NULL;
+       return 0;
 }
 
 static inline void bpf_prog_kallsyms_add(struct bpf_prog *fp)
index 800995c425e0860168efddd651fd6e08ca9d15d4..b792274189a3b00fe5a059bcba7a212d480bb52e 100644 (file)
@@ -86,15 +86,15 @@ struct ftrace_hash;
 
 #if defined(CONFIG_FUNCTION_TRACER) && defined(CONFIG_MODULES) && \
        defined(CONFIG_DYNAMIC_FTRACE)
-const char *
+int
 ftrace_mod_address_lookup(unsigned long addr, unsigned long *size,
                   unsigned long *off, char **modname, char *sym);
 #else
-static inline const char *
+static inline int
 ftrace_mod_address_lookup(unsigned long addr, unsigned long *size,
                   unsigned long *off, char **modname, char *sym)
 {
-       return NULL;
+       return 0;
 }
 #endif
 
index ffa1c603163c29e6da27f2cb7ccea90c99206720..330ffb59efe5119bca78242fc610d3fde108b15e 100644 (file)
@@ -931,11 +931,11 @@ int module_kallsyms_on_each_symbol(const char *modname,
  * least KSYM_NAME_LEN long: a pointer to namebuf is returned if
  * found, otherwise NULL.
  */
-const char *module_address_lookup(unsigned long addr,
-                                 unsigned long *symbolsize,
-                                 unsigned long *offset,
-                                 char **modname, const unsigned char **modbuildid,
-                                 char *namebuf);
+int module_address_lookup(unsigned long addr,
+                         unsigned long *symbolsize,
+                         unsigned long *offset,
+                         char **modname, const unsigned char **modbuildid,
+                         char *namebuf);
 int lookup_module_symbol_name(unsigned long addr, char *symname);
 int lookup_module_symbol_attrs(unsigned long addr,
                               unsigned long *size,
@@ -964,14 +964,14 @@ static inline int module_kallsyms_on_each_symbol(const char *modname,
 }
 
 /* For kallsyms to ask for address resolution.  NULL means not found. */
-static inline const char *module_address_lookup(unsigned long addr,
+static inline int module_address_lookup(unsigned long addr,
                                                unsigned long *symbolsize,
                                                unsigned long *offset,
                                                char **modname,
                                                const unsigned char **modbuildid,
                                                char *namebuf)
 {
-       return NULL;
+       return 0;
 }
 
 static inline int lookup_module_symbol_name(unsigned long addr, char *symname)
index 1a6c3faa6e4a19dfea0da74aa31e4b57c8ea0e06..695a0fb2cd4df4634c99516c080b7c4f0371af19 100644 (file)
@@ -736,11 +736,11 @@ static struct bpf_ksym *bpf_ksym_find(unsigned long addr)
        return n ? container_of(n, struct bpf_ksym, tnode) : NULL;
 }
 
-const char *__bpf_address_lookup(unsigned long addr, unsigned long *size,
+int __bpf_address_lookup(unsigned long addr, unsigned long *size,
                                 unsigned long *off, char *sym)
 {
        struct bpf_ksym *ksym;
-       char *ret = NULL;
+       int ret = 0;
 
        rcu_read_lock();
        ksym = bpf_ksym_find(addr);
@@ -748,9 +748,8 @@ const char *__bpf_address_lookup(unsigned long addr, unsigned long *size,
                unsigned long symbol_start = ksym->start;
                unsigned long symbol_end = ksym->end;
 
-               strscpy(sym, ksym->name, KSYM_NAME_LEN);
+               ret = strscpy(sym, ksym->name, KSYM_NAME_LEN);
 
-               ret = sym;
                if (size)
                        *size = symbol_end - symbol_start;
                if (off)
index 22ea19a36e6e673682885dddf3f71908b7f73622..98b9622d372e42fb29f390f3b8617d1d1b8c2616 100644 (file)
@@ -388,12 +388,12 @@ int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize,
               !!__bpf_address_lookup(addr, symbolsize, offset, namebuf);
 }
 
-static const char *kallsyms_lookup_buildid(unsigned long addr,
+static int kallsyms_lookup_buildid(unsigned long addr,
                        unsigned long *symbolsize,
                        unsigned long *offset, char **modname,
                        const unsigned char **modbuildid, char *namebuf)
 {
-       const char *ret;
+       int ret;
 
        namebuf[KSYM_NAME_LEN - 1] = 0;
        namebuf[0] = 0;
@@ -410,7 +410,7 @@ static const char *kallsyms_lookup_buildid(unsigned long addr,
                if (modbuildid)
                        *modbuildid = NULL;
 
-               ret = namebuf;
+               ret = strlen(namebuf);
                goto found;
        }
 
@@ -442,8 +442,13 @@ const char *kallsyms_lookup(unsigned long addr,
                            unsigned long *offset,
                            char **modname, char *namebuf)
 {
-       return kallsyms_lookup_buildid(addr, symbolsize, offset, modname,
-                                      NULL, namebuf);
+       int ret = kallsyms_lookup_buildid(addr, symbolsize, offset, modname,
+                                         NULL, namebuf);
+
+       if (!ret)
+               return NULL;
+
+       return namebuf;
 }
 
 int lookup_symbol_name(unsigned long addr, char *symname)
@@ -478,19 +483,15 @@ static int __sprint_symbol(char *buffer, unsigned long address,
 {
        char *modname;
        const unsigned char *buildid;
-       const char *name;
        unsigned long offset, size;
        int len;
 
        address += symbol_offset;
-       name = kallsyms_lookup_buildid(address, &size, &offset, &modname, &buildid,
+       len = kallsyms_lookup_buildid(address, &size, &offset, &modname, &buildid,
                                       buffer);
-       if (!name)
+       if (!len)
                return sprintf(buffer, "0x%lx", address - symbol_offset);
 
-       if (name != buffer)
-               strcpy(buffer, name);
-       len = strlen(buffer);
        offset -= symbol_offset;
 
        if (add_offset)
index 62fb57bb9f161cbbaa4a6310176318722bb54619..bf65e0c3c86fc0c6577a69955a8a5cc10a85df6c 100644 (file)
@@ -321,14 +321,15 @@ void * __weak dereference_module_function_descriptor(struct module *mod,
  * For kallsyms to ask for address resolution.  NULL means not found.  Careful
  * not to lock to avoid deadlock on oopses, simply disable preemption.
  */
-const char *module_address_lookup(unsigned long addr,
-                                 unsigned long *size,
-                           unsigned long *offset,
-                           char **modname,
-                           const unsigned char **modbuildid,
-                           char *namebuf)
+int module_address_lookup(unsigned long addr,
+                         unsigned long *size,
+                         unsigned long *offset,
+                         char **modname,
+                         const unsigned char **modbuildid,
+                         char *namebuf)
 {
-       const char *ret = NULL;
+       const char *sym;
+       int ret = 0;
        struct module *mod;
 
        preempt_disable();
@@ -344,12 +345,10 @@ const char *module_address_lookup(unsigned long addr,
 #endif
                }
 
-               ret = find_kallsyms_symbol(mod, addr, size, offset);
-       }
-       /* Make a copy in here where it's safe */
-       if (ret) {
-               strscpy(namebuf, ret, KSYM_NAME_LEN);
-               ret = namebuf;
+               sym = find_kallsyms_symbol(mod, addr, size, offset);
+
+               if (sym)
+                       ret = strscpy(namebuf, sym, KSYM_NAME_LEN);
        }
        preempt_enable();
 
index 65208d3b5ed983c10a00672bc37fc07dbf9232de..eacab4020508eebef09646bc7edfa7a0b44cb8c0 100644 (file)
@@ -6969,7 +6969,7 @@ allocate_ftrace_mod_map(struct module *mod,
        return mod_map;
 }
 
-static const char *
+static int
 ftrace_func_address_lookup(struct ftrace_mod_map *mod_map,
                           unsigned long addr, unsigned long *size,
                           unsigned long *off, char *sym)
@@ -6990,21 +6990,18 @@ ftrace_func_address_lookup(struct ftrace_mod_map *mod_map,
                        *size = found_func->size;
                if (off)
                        *off = addr - found_func->ip;
-               if (sym)
-                       strscpy(sym, found_func->name, KSYM_NAME_LEN);
-
-               return found_func->name;
+               return strscpy(sym, found_func->name, KSYM_NAME_LEN);
        }
 
-       return NULL;
+       return 0;
 }
 
-const char *
+int
 ftrace_mod_address_lookup(unsigned long addr, unsigned long *size,
                   unsigned long *off, char **modname, char *sym)
 {
        struct ftrace_mod_map *mod_map;
-       const char *ret = NULL;
+       int ret = 0;
 
        /* mod_map is freed via call_rcu() */
        preempt_disable();