From eaf38dc2bbb22ae23f4b9324a54c3cb34f6b57b4 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Wed, 9 Sep 2020 14:52:54 -0700 Subject: [PATCH] ANDROID: kallsyms: ignore ThinLTO+CFI hash suffix in kallsyms_lookup_name() Similar to commit f683c8dc7f32 ("ANDROID: kallsyms: strip hashes from static functions with ThinLTO and CFI"), since LLVM adds a hash to static function names when CONFIG_THINLTO and CFI are enabled, callers of kallsyms_lookup_name() which aren't aware of the additional suffix will fail to find the symbol. One example is kprobes (both compiled and the dynamic events) which rely on this to resolve the function name to attach a kprobe/kretprobe to. Address this by also calling the cleanup_symbol_name() helper from kallsyms_lookup_name() when failing to match a symbol by name. This will strip off the hash suffix, if any, and attempt the strcmp() again. Bug: 167595670 Change-Id: I4c79c818c29b4b82a94a5a7e86ae9783a41e853d Signed-off-by: Jack Pham --- kernel/kallsyms.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index a4f6dd5a6089..14de0c7bf756 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c @@ -159,6 +159,26 @@ static unsigned long kallsyms_sym_address(int idx) return kallsyms_relative_base - 1 - kallsyms_offsets[idx]; } +#if defined(CONFIG_CFI_CLANG) && defined(CONFIG_THINLTO) +/* + * LLVM appends a hash to static function names when ThinLTO and CFI are + * both enabled, which causes confusion and potentially breaks user space + * tools, so we will strip the postfix from expanded symbol names. + */ +static inline char *cleanup_symbol_name(char *s) +{ + char *res = NULL; + + res = strrchr(s, '$'); + if (res) + *res = '\0'; + + return res; +} +#else +static inline char *cleanup_symbol_name(char *s) { return NULL; } +#endif + /* Lookup the address for this symbol. Returns 0 if not found. */ unsigned long kallsyms_lookup_name(const char *name) { @@ -171,6 +191,9 @@ unsigned long kallsyms_lookup_name(const char *name) if (strcmp(namebuf, name) == 0) return kallsyms_sym_address(i); + + if (cleanup_symbol_name(namebuf) && strcmp(namebuf, name) == 0) + return kallsyms_sym_address(i); } return module_kallsyms_lookup_name(name); } @@ -269,24 +292,6 @@ int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize, !!__bpf_address_lookup(addr, symbolsize, offset, namebuf); } -#if defined(CONFIG_CFI_CLANG) && defined(CONFIG_THINLTO) -/* - * LLVM appends a hash to static function names when ThinLTO and CFI are - * both enabled, which causes confusion and potentially breaks user space - * tools, so we will strip the postfix from expanded symbol names. - */ -static inline void cleanup_symbol_name(char *s) -{ - char *res; - - res = strrchr(s, '$'); - if (res) - *res = '\0'; -} -#else -static inline void cleanup_symbol_name(char *s) {} -#endif - /* * Lookup an address * - modname is set to NULL if it's in the kernel.