Skip to content

Commit 9a7714b

Browse files
author
git apple-llvm automerger
committed
Merge commit '9ed4c705ac1c' from llvm.org/main into next
2 parents 00005ed + 9ed4c70 commit 9a7714b

File tree

5 files changed

+56
-68
lines changed

5 files changed

+56
-68
lines changed

clang/lib/CodeGen/SanitizerMetadata.cpp

Lines changed: 5 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -32,37 +32,6 @@ static SanitizerMask expandKernelSanitizerMasks(SanitizerMask Mask) {
3232
return Mask;
3333
}
3434

35-
static bool shouldTagGlobal(const llvm::GlobalVariable &G) {
36-
// For now, don't instrument constant data, as it'll be in .rodata anyway. It
37-
// may be worth instrumenting these in future to stop them from being used as
38-
// gadgets.
39-
if (G.getName().starts_with("llvm.") || G.isThreadLocal() || G.isConstant())
40-
return false;
41-
42-
// Globals can be placed implicitly or explicitly in sections. There's two
43-
// different types of globals that meet this criteria that cause problems:
44-
// 1. Function pointers that are going into various init arrays (either
45-
// explicitly through `__attribute__((section(<foo>)))` or implicitly
46-
// through `__attribute__((constructor)))`, such as ".(pre)init(_array)",
47-
// ".fini(_array)", ".ctors", and ".dtors". These function pointers end up
48-
// overaligned and overpadded, making iterating over them problematic, and
49-
// each function pointer is individually tagged (so the iteration over
50-
// them causes SIGSEGV/MTE[AS]ERR).
51-
// 2. Global variables put into an explicit section, where the section's name
52-
// is a valid C-style identifier. The linker emits a `__start_<name>` and
53-
// `__stop_<name>` symbol for the section, so that you can iterate over
54-
// globals within this section. Unfortunately, again, these globals would
55-
// be tagged and so iteration causes SIGSEGV/MTE[AS]ERR.
56-
//
57-
// To mitigate both these cases, and because specifying a section is rare
58-
// outside of these two cases, disable MTE protection for globals in any
59-
// section.
60-
if (G.hasSection())
61-
return false;
62-
63-
return true;
64-
}
65-
6635
void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV,
6736
SourceLocation Loc, StringRef Name,
6837
QualType Ty,
@@ -89,15 +58,11 @@ void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV,
8958
Meta.NoHWAddress |= CGM.isInNoSanitizeList(
9059
FsanitizeArgument.Mask & SanitizerKind::HWAddress, GV, Loc, Ty);
9160

92-
if (shouldTagGlobal(*GV)) {
93-
Meta.Memtag |= static_cast<bool>(FsanitizeArgument.Mask &
94-
SanitizerKind::MemtagGlobals);
95-
Meta.Memtag &= !NoSanitizeAttrSet.hasOneOf(SanitizerKind::MemTag);
96-
Meta.Memtag &= !CGM.isInNoSanitizeList(
97-
FsanitizeArgument.Mask & SanitizerKind::MemTag, GV, Loc, Ty);
98-
} else {
99-
Meta.Memtag = false;
100-
}
61+
Meta.Memtag |=
62+
static_cast<bool>(FsanitizeArgument.Mask & SanitizerKind::MemtagGlobals);
63+
Meta.Memtag &= !NoSanitizeAttrSet.hasOneOf(SanitizerKind::MemTag);
64+
Meta.Memtag &= !CGM.isInNoSanitizeList(
65+
FsanitizeArgument.Mask & SanitizerKind::MemTag, GV, Loc, Ty);
10166

10267
Meta.IsDynInit = IsDynInit && !Meta.NoAddress &&
10368
FsanitizeArgument.has(SanitizerKind::Address) &&

clang/test/CodeGen/memtag-globals.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ void func() {
2525
// CHECK: @{{.*}}extra_global{{.*}} ={{.*}} sanitize_memtag
2626
// CHECK: @{{.*}}global{{.*}} ={{.*}} sanitize_memtag
2727

28-
// CHECK: @{{.*}}section_global{{.*}} =
29-
// CHECK-NOT: sanitize_memtag
28+
// This DOES NOT mean we are instrumenting the section global,
29+
// but we are ignoring it in AsmPrinter rather than in clang.
30+
// CHECK: @{{.*}}section_global{{.*}} ={{.*}} sanitize_memtag
3031
// CHECK: @{{.*}}attributed_global{{.*}} =
3132
// CHECK-NOT: sanitize_memtag
3233
// CHECK: @{{.*}}disable_instrumentation_global{{.*}} =
@@ -35,7 +36,7 @@ void func() {
3536
// CHECK-NOT: sanitize_memtag
3637

3738
// CHECK: @{{.*}}static_var{{.*}} ={{.*}} sanitize_memtag
38-
// CHECK: @{{.*}} = {{.*}} c"Hello, world!\00"{{.*}}
39+
// CHECK: @{{.*}} = {{.*}} c"Hello, world!\00"{{.*}} sanitize_memtag
3940
// CHECK: @{{.*}}external_global{{.*}} ={{.*}} sanitize_memtag
4041

4142
// IGNORELIST: @{{.*}}extra_global{{.*}} ={{.*}} sanitize_memtag

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2423,6 +2423,41 @@ void AsmPrinter::emitRemarksSection(remarks::RemarkStreamer &RS) {
24232423
OutStreamer->emitBinaryData(Buf);
24242424
}
24252425

2426+
static bool shouldTagGlobal(const llvm::GlobalVariable &G) {
2427+
// We used to do this in clang, but there are optimization passes that turn
2428+
// non-constant globals into constants. So now, clang only tells us whether
2429+
// it would *like* a global to be tagged, but we still make the decision here.
2430+
//
2431+
// For now, don't instrument constant data, as it'll be in .rodata anyway. It
2432+
// may be worth instrumenting these in future to stop them from being used as
2433+
// gadgets.
2434+
if (G.getName().starts_with("llvm.") || G.isThreadLocal() || G.isConstant())
2435+
return false;
2436+
2437+
// Globals can be placed implicitly or explicitly in sections. There's two
2438+
// different types of globals that meet this criteria that cause problems:
2439+
// 1. Function pointers that are going into various init arrays (either
2440+
// explicitly through `__attribute__((section(<foo>)))` or implicitly
2441+
// through `__attribute__((constructor)))`, such as ".(pre)init(_array)",
2442+
// ".fini(_array)", ".ctors", and ".dtors". These function pointers end up
2443+
// overaligned and overpadded, making iterating over them problematic, and
2444+
// each function pointer is individually tagged (so the iteration over
2445+
// them causes SIGSEGV/MTE[AS]ERR).
2446+
// 2. Global variables put into an explicit section, where the section's name
2447+
// is a valid C-style identifier. The linker emits a `__start_<name>` and
2448+
// `__stop_<name>` symbol for the section, so that you can iterate over
2449+
// globals within this section. Unfortunately, again, these globals would
2450+
// be tagged and so iteration causes SIGSEGV/MTE[AS]ERR.
2451+
//
2452+
// To mitigate both these cases, and because specifying a section is rare
2453+
// outside of these two cases, disable MTE protection for globals in any
2454+
// section.
2455+
if (G.hasSection())
2456+
return false;
2457+
2458+
return true;
2459+
}
2460+
24262461
static void tagGlobalDefinition(Module &M, GlobalVariable *G) {
24272462
Constant *Initializer = G->getInitializer();
24282463
uint64_t SizeInBytes =
@@ -2455,6 +2490,12 @@ static void tagGlobalDefinition(Module &M, GlobalVariable *G) {
24552490
G->setUnnamedAddr(GlobalValue::UnnamedAddr::None);
24562491
}
24572492

2493+
static void removeMemtagFromGlobal(GlobalVariable &G) {
2494+
auto Meta = G.getSanitizerMetadata();
2495+
Meta.Memtag = false;
2496+
G.setSanitizerMetadata(Meta);
2497+
}
2498+
24582499
bool AsmPrinter::doFinalization(Module &M) {
24592500
// Set the MachineFunction to nullptr so that we can catch attempted
24602501
// accesses to MF specific features at the module level and so that
@@ -2465,6 +2506,12 @@ bool AsmPrinter::doFinalization(Module &M) {
24652506
for (GlobalVariable &G : M.globals()) {
24662507
if (G.isDeclaration() || !G.isTagged())
24672508
continue;
2509+
if (!shouldTagGlobal(G)) {
2510+
assert(G.hasSanitizerMetadata()); // because isTagged.
2511+
removeMemtagFromGlobal(G);
2512+
assert(!G.isTagged());
2513+
continue;
2514+
}
24682515
GlobalsToTag.push_back(&G);
24692516
}
24702517
for (GlobalVariable *G : GlobalsToTag)

llvm/lib/IR/Verifier.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -808,10 +808,6 @@ void Verifier::visitGlobalValue(const GlobalValue &GV) {
808808
"visibility must be dso_local!",
809809
&GV);
810810

811-
if (GV.isTagged()) {
812-
Check(!GV.hasSection(), "tagged GlobalValue must not be in section.", &GV);
813-
}
814-
815811
forEachUser(&GV, GlobalValueVisited, [&](const Value *V) -> bool {
816812
if (const Instruction *I = dyn_cast<Instruction>(V)) {
817813
if (!I->getParent() || !I->getParent()->getParent())

llvm/unittests/IR/VerifierTest.cpp

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -416,26 +416,5 @@ TEST(VerifierTest, GetElementPtrInst) {
416416
<< Error;
417417
}
418418

419-
TEST(VerifierTest, DetectTaggedGlobalInSection) {
420-
LLVMContext C;
421-
Module M("M", C);
422-
GlobalVariable *GV = new GlobalVariable(
423-
Type::getInt64Ty(C), false, GlobalValue::InternalLinkage,
424-
ConstantInt::get(Type::getInt64Ty(C), 1));
425-
GV->setDSOLocal(true);
426-
GlobalValue::SanitizerMetadata MD{};
427-
MD.Memtag = true;
428-
GV->setSanitizerMetadata(MD);
429-
GV->setSection("foo");
430-
M.insertGlobalVariable(GV);
431-
432-
std::string Error;
433-
raw_string_ostream ErrorOS(Error);
434-
EXPECT_TRUE(verifyModule(M, &ErrorOS));
435-
EXPECT_TRUE(
436-
StringRef(Error).starts_with("tagged GlobalValue must not be in section"))
437-
<< Error;
438-
}
439-
440419
} // end anonymous namespace
441420
} // end namespace llvm

0 commit comments

Comments
 (0)