Skip to content

Commit 8b8e6b5

Browse files
samitolvanenkees
authored andcommitted
kallsyms: strip ThinLTO hashes from static functions
With CONFIG_CFI_CLANG and ThinLTO, Clang appends a hash to the names of all static functions not marked __used. This can break userspace tools that don't expect the function name to change, so strip out the hash from the output. Suggested-by: Jack Pham <jackp@codeaurora.org> Signed-off-by: Sami Tolvanen <samitolvanen@google.com> Reviewed-by: Kees Cook <keescook@chromium.org> Tested-by: Nathan Chancellor <nathan@kernel.org> Signed-off-by: Kees Cook <keescook@chromium.org> Link: https://lore.kernel.org/r/20210408182843.1754385-8-samitolvanen@google.com
1 parent 0a5b412 commit 8b8e6b5

1 file changed

Lines changed: 50 additions & 5 deletions

File tree

kernel/kallsyms.c

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,27 @@ static unsigned long kallsyms_sym_address(int idx)
161161
return kallsyms_relative_base - 1 - kallsyms_offsets[idx];
162162
}
163163

164+
#if defined(CONFIG_CFI_CLANG) && defined(CONFIG_LTO_CLANG_THIN)
165+
/*
166+
* LLVM appends a hash to static function names when ThinLTO and CFI are
167+
* both enabled, i.e. foo() becomes foo$707af9a22804d33c81801f27dcfe489b.
168+
* This causes confusion and potentially breaks user space tools, so we
169+
* strip the suffix from expanded symbol names.
170+
*/
171+
static inline bool cleanup_symbol_name(char *s)
172+
{
173+
char *res;
174+
175+
res = strrchr(s, '$');
176+
if (res)
177+
*res = '\0';
178+
179+
return res != NULL;
180+
}
181+
#else
182+
static inline bool cleanup_symbol_name(char *s) { return false; }
183+
#endif
184+
164185
/* Lookup the address for this symbol. Returns 0 if not found. */
165186
unsigned long kallsyms_lookup_name(const char *name)
166187
{
@@ -173,6 +194,9 @@ unsigned long kallsyms_lookup_name(const char *name)
173194

174195
if (strcmp(namebuf, name) == 0)
175196
return kallsyms_sym_address(i);
197+
198+
if (cleanup_symbol_name(namebuf) && strcmp(namebuf, name) == 0)
199+
return kallsyms_sym_address(i);
176200
}
177201
return module_kallsyms_lookup_name(name);
178202
}
@@ -303,7 +327,9 @@ const char *kallsyms_lookup(unsigned long addr,
303327
namebuf, KSYM_NAME_LEN);
304328
if (modname)
305329
*modname = NULL;
306-
return namebuf;
330+
331+
ret = namebuf;
332+
goto found;
307333
}
308334

309335
/* See if it's in a module or a BPF JITed image. */
@@ -316,11 +342,16 @@ const char *kallsyms_lookup(unsigned long addr,
316342
if (!ret)
317343
ret = ftrace_mod_address_lookup(addr, symbolsize,
318344
offset, modname, namebuf);
345+
346+
found:
347+
cleanup_symbol_name(namebuf);
319348
return ret;
320349
}
321350

322351
int lookup_symbol_name(unsigned long addr, char *symname)
323352
{
353+
int res;
354+
324355
symname[0] = '\0';
325356
symname[KSYM_NAME_LEN - 1] = '\0';
326357

@@ -331,15 +362,23 @@ int lookup_symbol_name(unsigned long addr, char *symname)
331362
/* Grab name */
332363
kallsyms_expand_symbol(get_symbol_offset(pos),
333364
symname, KSYM_NAME_LEN);
334-
return 0;
365+
goto found;
335366
}
336367
/* See if it's in a module. */
337-
return lookup_module_symbol_name(addr, symname);
368+
res = lookup_module_symbol_name(addr, symname);
369+
if (res)
370+
return res;
371+
372+
found:
373+
cleanup_symbol_name(symname);
374+
return 0;
338375
}
339376

340377
int lookup_symbol_attrs(unsigned long addr, unsigned long *size,
341378
unsigned long *offset, char *modname, char *name)
342379
{
380+
int res;
381+
343382
name[0] = '\0';
344383
name[KSYM_NAME_LEN - 1] = '\0';
345384

@@ -351,10 +390,16 @@ int lookup_symbol_attrs(unsigned long addr, unsigned long *size,
351390
kallsyms_expand_symbol(get_symbol_offset(pos),
352391
name, KSYM_NAME_LEN);
353392
modname[0] = '\0';
354-
return 0;
393+
goto found;
355394
}
356395
/* See if it's in a module. */
357-
return lookup_module_symbol_attrs(addr, size, offset, modname, name);
396+
res = lookup_module_symbol_attrs(addr, size, offset, modname, name);
397+
if (res)
398+
return res;
399+
400+
found:
401+
cleanup_symbol_name(name);
402+
return 0;
358403
}
359404

360405
/* Look up a kernel symbol and return it in a text buffer. */

0 commit comments

Comments
 (0)