@@ -2398,6 +2398,41 @@ void AsmPrinter::emitRemarksSection(remarks::RemarkStreamer &RS) {
23982398 OutStreamer->emitBinaryData (Buf);
23992399}
24002400
2401+ static bool shouldTagGlobal (const llvm::GlobalVariable &G) {
2402+ // We used to do this in clang, but there are optimization passes that turn
2403+ // non-constant globals into constants. So now, clang only tells us whether
2404+ // it would *like* a global to be tagged, but we still make the decision here.
2405+ //
2406+ // For now, don't instrument constant data, as it'll be in .rodata anyway. It
2407+ // may be worth instrumenting these in future to stop them from being used as
2408+ // gadgets.
2409+ if (G.getName ().starts_with (" llvm." ) || G.isThreadLocal () || G.isConstant ())
2410+ return false ;
2411+
2412+ // Globals can be placed implicitly or explicitly in sections. There's two
2413+ // different types of globals that meet this criteria that cause problems:
2414+ // 1. Function pointers that are going into various init arrays (either
2415+ // explicitly through `__attribute__((section(<foo>)))` or implicitly
2416+ // through `__attribute__((constructor)))`, such as ".(pre)init(_array)",
2417+ // ".fini(_array)", ".ctors", and ".dtors". These function pointers end up
2418+ // overaligned and overpadded, making iterating over them problematic, and
2419+ // each function pointer is individually tagged (so the iteration over
2420+ // them causes SIGSEGV/MTE[AS]ERR).
2421+ // 2. Global variables put into an explicit section, where the section's name
2422+ // is a valid C-style identifier. The linker emits a `__start_<name>` and
2423+ // `__stop_<name>` symbol for the section, so that you can iterate over
2424+ // globals within this section. Unfortunately, again, these globals would
2425+ // be tagged and so iteration causes SIGSEGV/MTE[AS]ERR.
2426+ //
2427+ // To mitigate both these cases, and because specifying a section is rare
2428+ // outside of these two cases, disable MTE protection for globals in any
2429+ // section.
2430+ if (G.hasSection ())
2431+ return false ;
2432+
2433+ return true ;
2434+ }
2435+
24012436static void tagGlobalDefinition (Module &M, GlobalVariable *G) {
24022437 Constant *Initializer = G->getInitializer ();
24032438 uint64_t SizeInBytes =
@@ -2430,6 +2465,12 @@ static void tagGlobalDefinition(Module &M, GlobalVariable *G) {
24302465 G->setUnnamedAddr (GlobalValue::UnnamedAddr::None);
24312466}
24322467
2468+ static void removeMemtagFromGlobal (GlobalVariable &G) {
2469+ auto Meta = G.getSanitizerMetadata ();
2470+ Meta.Memtag = false ;
2471+ G.setSanitizerMetadata (Meta);
2472+ }
2473+
24332474bool AsmPrinter::doFinalization (Module &M) {
24342475 // Set the MachineFunction to nullptr so that we can catch attempted
24352476 // accesses to MF specific features at the module level and so that
@@ -2440,6 +2481,12 @@ bool AsmPrinter::doFinalization(Module &M) {
24402481 for (GlobalVariable &G : M.globals ()) {
24412482 if (G.isDeclaration () || !G.isTagged ())
24422483 continue ;
2484+ if (!shouldTagGlobal (G)) {
2485+ assert (G.hasSanitizerMetadata ()); // because isTagged.
2486+ removeMemtagFromGlobal (G);
2487+ assert (!G.isTagged ());
2488+ continue ;
2489+ }
24432490 GlobalsToTag.push_back (&G);
24442491 }
24452492 for (GlobalVariable *G : GlobalsToTag)
0 commit comments