Commit 6eb4bd92 authored by Nick Desaulniers's avatar Nick Desaulniers Committed by Kees Cook

kallsyms: strip LTO suffixes from static functions

Similar to:
commit 8b8e6b5d ("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/rGc6e5c4654bd5045fe22a1a52779e48e2038a404cReported-by: default avatarKE.LI(Lieke) <like1@oppo.com>
Suggested-by: default avatarNathan Chancellor <nathan@kernel.org>
Suggested-by: default avatarPadmanabha Srinivasaiah <treasure4paddy@gmail.com>
Suggested-by: default avatarSami Tolvanen <samitolvanen@google.com>
Reviewed-by: default avatarNathan Chancellor <nathan@kernel.org>
Reviewed-by: default avatarFangrui Song <maskray@google.com>
Reviewed-by: default avatarSami Tolvanen <samitolvanen@google.com>
Signed-off-by: default avatarNick Desaulniers <ndesaulniers@google.com>
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20211004162936.21961-1-ndesaulniers@google.com
parent 4c78c727
...@@ -164,26 +164,46 @@ static unsigned long kallsyms_sym_address(int idx) ...@@ -164,26 +164,46 @@ static unsigned long kallsyms_sym_address(int idx)
return kallsyms_relative_base - 1 - kallsyms_offsets[idx]; return kallsyms_relative_base - 1 - kallsyms_offsets[idx];
} }
#if defined(CONFIG_CFI_CLANG) && defined(CONFIG_LTO_CLANG_THIN) static bool cleanup_symbol_name(char *s)
/*
* LLVM appends a hash to static function names when ThinLTO and CFI are
* both enabled, i.e. foo() becomes foo$707af9a22804d33c81801f27dcfe489b.
* This causes confusion and potentially breaks user space tools, so we
* strip the suffix from expanded symbol names.
*/
static inline bool cleanup_symbol_name(char *s)
{ {
char *res; char *res;
if (!IS_ENABLED(CONFIG_LTO_CLANG))
return false;
/*
* LLVM appends various suffixes for local functions and variables that
* must be promoted to global scope as part of LTO. This can break
* hooking of static functions with kprobes. '.' is not a valid
* character in an identifier in C. Suffixes observed:
* - foo.llvm.[0-9a-f]+
* - foo.[0-9a-f]+
* - foo.[0-9a-f]+.cfi_jt
*/
res = strchr(s, '.');
if (res) {
*res = '\0';
return true;
}
if (!IS_ENABLED(CONFIG_CFI_CLANG) ||
!IS_ENABLED(CONFIG_LTO_CLANG_THIN) ||
CONFIG_CLANG_VERSION >= 130000)
return false;
/*
* Prior to LLVM 13, the following suffixes were observed when thinLTO
* and CFI are both enabled:
* - foo$[0-9]+
*/
res = strrchr(s, '$'); res = strrchr(s, '$');
if (res) if (res) {
*res = '\0'; *res = '\0';
return true;
}
return res != NULL; return false;
} }
#else
static inline bool cleanup_symbol_name(char *s) { return false; }
#endif
/* Lookup the address for this symbol. Returns 0 if not found. */ /* Lookup the address for this symbol. Returns 0 if not found. */
unsigned long kallsyms_lookup_name(const char *name) unsigned long kallsyms_lookup_name(const char *name)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment