Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

authored by

Sami Tolvanen and committed by
Kees Cook
8b8e6b5d 0a5b4128

+50 -5
+50 -5
kernel/kallsyms.c
··· 161 161 return kallsyms_relative_base - 1 - kallsyms_offsets[idx]; 162 162 } 163 163 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 + 164 185 /* Lookup the address for this symbol. Returns 0 if not found. */ 165 186 unsigned long kallsyms_lookup_name(const char *name) 166 187 { ··· 193 172 off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf)); 194 173 195 174 if (strcmp(namebuf, name) == 0) 175 + return kallsyms_sym_address(i); 176 + 177 + if (cleanup_symbol_name(namebuf) && strcmp(namebuf, name) == 0) 196 178 return kallsyms_sym_address(i); 197 179 } 198 180 return module_kallsyms_lookup_name(name); ··· 327 303 namebuf, KSYM_NAME_LEN); 328 304 if (modname) 329 305 *modname = NULL; 330 - return namebuf; 306 + 307 + ret = namebuf; 308 + goto found; 331 309 } 332 310 333 311 /* See if it's in a module or a BPF JITed image. */ ··· 342 316 if (!ret) 343 317 ret = ftrace_mod_address_lookup(addr, symbolsize, 344 318 offset, modname, namebuf); 319 + 320 + found: 321 + cleanup_symbol_name(namebuf); 345 322 return ret; 346 323 } 347 324 348 325 int lookup_symbol_name(unsigned long addr, char *symname) 349 326 { 327 + int res; 328 + 350 329 symname[0] = '\0'; 351 330 symname[KSYM_NAME_LEN - 1] = '\0'; 352 331 ··· 362 331 /* Grab name */ 363 332 kallsyms_expand_symbol(get_symbol_offset(pos), 364 333 symname, KSYM_NAME_LEN); 365 - return 0; 334 + goto found; 366 335 } 367 336 /* See if it's in a module. */ 368 - return lookup_module_symbol_name(addr, symname); 337 + res = lookup_module_symbol_name(addr, symname); 338 + if (res) 339 + return res; 340 + 341 + found: 342 + cleanup_symbol_name(symname); 343 + return 0; 369 344 } 370 345 371 346 int lookup_symbol_attrs(unsigned long addr, unsigned long *size, 372 347 unsigned long *offset, char *modname, char *name) 373 348 { 349 + int res; 350 + 374 351 name[0] = '\0'; 375 352 name[KSYM_NAME_LEN - 1] = '\0'; 376 353 ··· 390 351 kallsyms_expand_symbol(get_symbol_offset(pos), 391 352 name, KSYM_NAME_LEN); 392 353 modname[0] = '\0'; 393 - return 0; 354 + goto found; 394 355 } 395 356 /* See if it's in a module. */ 396 - return lookup_module_symbol_attrs(addr, size, offset, modname, name); 357 + res = lookup_module_symbol_attrs(addr, size, offset, modname, name); 358 + if (res) 359 + return res; 360 + 361 + found: 362 + cleanup_symbol_name(name); 363 + return 0; 397 364 } 398 365 399 366 /* Look up a kernel symbol and return it in a text buffer. */