Skip to content

Commit 6eb4bd9

Browse files
nickdesaulnierskees
authored andcommitted
kallsyms: strip LTO suffixes from static functions
Similar to: commit 8b8e6b5 ("kallsyms: strip ThinLTO hashes from static functions") It's very common for compilers to modify the symbol name for static functions as part of optimizing transformations. That makes hooking static functions (that weren't inlined or DCE'd) with kprobes difficult. LLVM has yet another name mangling scheme used by thin LTO. Combine handling of the various schemes by truncating after the first '.'. Strip off these suffixes so that we can continue to hook such static functions. Clang releases prior to clang-13 would use '$' instead of '.' Link: https://reviews.llvm.org/rGc6e5c4654bd5045fe22a1a52779e48e2038a404c Reported-by: KE.LI(Lieke) <[email protected]> Suggested-by: Nathan Chancellor <[email protected]> Suggested-by: Padmanabha Srinivasaiah <[email protected]> Suggested-by: Sami Tolvanen <[email protected]> Reviewed-by: Nathan Chancellor <[email protected]> Reviewed-by: Fangrui Song <[email protected]> Reviewed-by: Sami Tolvanen <[email protected]> Signed-off-by: Nick Desaulniers <[email protected]> Signed-off-by: Kees Cook <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 4c78c72 commit 6eb4bd9

File tree

1 file changed

+33
-13
lines changed

1 file changed

+33
-13
lines changed

kernel/kallsyms.c

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -164,26 +164,46 @@ static unsigned long kallsyms_sym_address(int idx)
164164
return kallsyms_relative_base - 1 - kallsyms_offsets[idx];
165165
}
166166

167-
#if defined(CONFIG_CFI_CLANG) && defined(CONFIG_LTO_CLANG_THIN)
168-
/*
169-
* LLVM appends a hash to static function names when ThinLTO and CFI are
170-
* both enabled, i.e. foo() becomes foo$707af9a22804d33c81801f27dcfe489b.
171-
* This causes confusion and potentially breaks user space tools, so we
172-
* strip the suffix from expanded symbol names.
173-
*/
174-
static inline bool cleanup_symbol_name(char *s)
167+
static bool cleanup_symbol_name(char *s)
175168
{
176169
char *res;
177170

171+
if (!IS_ENABLED(CONFIG_LTO_CLANG))
172+
return false;
173+
174+
/*
175+
* LLVM appends various suffixes for local functions and variables that
176+
* must be promoted to global scope as part of LTO. This can break
177+
* hooking of static functions with kprobes. '.' is not a valid
178+
* character in an identifier in C. Suffixes observed:
179+
* - foo.llvm.[0-9a-f]+
180+
* - foo.[0-9a-f]+
181+
* - foo.[0-9a-f]+.cfi_jt
182+
*/
183+
res = strchr(s, '.');
184+
if (res) {
185+
*res = '\0';
186+
return true;
187+
}
188+
189+
if (!IS_ENABLED(CONFIG_CFI_CLANG) ||
190+
!IS_ENABLED(CONFIG_LTO_CLANG_THIN) ||
191+
CONFIG_CLANG_VERSION >= 130000)
192+
return false;
193+
194+
/*
195+
* Prior to LLVM 13, the following suffixes were observed when thinLTO
196+
* and CFI are both enabled:
197+
* - foo$[0-9]+
198+
*/
178199
res = strrchr(s, '$');
179-
if (res)
200+
if (res) {
180201
*res = '\0';
202+
return true;
203+
}
181204

182-
return res != NULL;
205+
return false;
183206
}
184-
#else
185-
static inline bool cleanup_symbol_name(char *s) { return false; }
186-
#endif
187207

188208
/* Lookup the address for this symbol. Returns 0 if not found. */
189209
unsigned long kallsyms_lookup_name(const char *name)

0 commit comments

Comments
 (0)