-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Disable memtag sanitization for global fnptrs going into .ctors #70186
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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 llvm#69939
@llvm/pr-subscribers-backend-aarch64 @llvm/pr-subscribers-clang Author: Mitch Phillips (hctim) ChangesLooks like there's code out there that, instead of using Problem is, with memtag-globals, we pad the global function pointer to Fixes #69939 Full diff: https://github.com/llvm/llvm-project/pull/70186.diff 2 Files Affected:
diff --git a/clang/test/CodeGen/memtag-globals-asm.cpp b/clang/test/CodeGen/memtag-globals-asm.cpp
index 3f18671562def71..4b76b394e0c1dc3 100644
--- a/clang/test/CodeGen/memtag-globals-asm.cpp
+++ b/clang/test/CodeGen/memtag-globals-asm.cpp
@@ -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
diff --git a/llvm/lib/Target/AArch64/AArch64GlobalsTagging.cpp b/llvm/lib/Target/AArch64/AArch64GlobalsTagging.cpp
index 2ed668712897ce7..88e44eb0bfbb99f 100644
--- a/llvm/lib/Target/AArch64/AArch64GlobalsTagging.cpp
+++ b/llvm/lib/Target/AArch64/AArch64GlobalsTagging.cpp
@@ -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;
}
|
Dear Mitch, thank you for your PR! UPD. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
(friendly ping @eugenis / @vitalybuka) |
Previous work in this area (#70186) disabled MTE in constructor sections. Looks like I missed one, ".preinit_array". Also, in the meantime, I found an exciting feature in the linker where globals placed into an explicit section, where the section name is a valid C identifer, gets an implicit '__start_<sectionname>' and '__stop_<sectionname>' symbol as well. This is convenient for iterating over some globals, but of course iteration over differently-tagged globals in MTE explodes. Thus, disable MTE globals for anything that has a section.
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