Disable memtag sanitization for global fnptrs going into .ctors (#70186)

Looks like there's code out there that, instead of using
'__attribute__((constructor(x)))' to add constructor functions, they
just declare a global function pointer and use
'__attribute__((section('.ctors')))' instead.

Problem is, with memtag-globals, we pad the global function pointer to
be 16 bytes large. This of course means we have an 8-byte real function
pointer, then 8 bytes of zero padding, and this trips up the loader when
it processes this section.

Fixes #69939
This commit is contained in:
Mitch Phillips 2023-11-01 11:43:28 +01:00 committed by GitHub
parent 0b5e0fb62d
commit ba31ed4725
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 0 deletions

View File

@ -259,3 +259,23 @@ int f(int x) {
// CHECK-Q-DAG: ldr {{.*}}, [[[REG_O2]]]
function_int;
}
typedef void (*func_t)(void);
#define CONSTRUCTOR(section_name) \
__attribute__((used)) __attribute__((section(section_name)))
__attribute__((constructor(0))) void func_constructor() {}
CONSTRUCTOR(".init") func_t func_init = func_constructor;
CONSTRUCTOR(".fini") func_t func_fini = func_constructor;
CONSTRUCTOR(".ctors") func_t func_ctors = func_constructor;
CONSTRUCTOR(".dtors") func_t func_dtors = func_constructor;
CONSTRUCTOR(".init_array") func_t func_init_array = func_constructor;
CONSTRUCTOR(".fini_array") func_t func_fini_array = func_constructor;
// CHECK-NOT: .memtag func_constructor
// CHECK-NOT: .memtag func_init
// CHECK-NOT: .memtag func_fini
// CHECK-NOT: .memtag func_ctors
// CHECK-NOT: .memtag func_dtors
// CHECK-NOT: .memtag func_init_array
// CHECK-NOT: .memtag func_fini_array

View File

@ -43,6 +43,18 @@ static bool shouldTagGlobal(GlobalVariable &G) {
return false;
}
// Don't instrument function pointers that are going into various init arrays
// via `__attribute__((section(<foo>)))`:
// https://github.com/llvm/llvm-project/issues/69939
if (G.hasSection() &&
(G.getSection() == ".init" || G.getSection() == ".fini" ||
G.getSection() == ".init_array" || G.getSection() == ".fini_array" ||
G.getSection() == ".ctors" || G.getSection() == ".dtors")) {
Meta.Memtag = false;
G.setSanitizerMetadata(Meta);
return false;
}
return true;
}