Skip to content

Commit 161d00f

Browse files
authored
[Sanitizers] Add support for -sanitize=memtag-stack (#85515)
This sanitizer adds MTE (memory tagging extension) checks to stack variable accesses. Enablement simply requires setting an attribute on function definitions, and the instrumentation is added by LLVM. The corresponding swift-driver change is at: swiftlang/swift-driver#2016. rdar://161721201
1 parent 8c12e00 commit 161d00f

File tree

6 files changed

+76
-5
lines changed

6 files changed

+76
-5
lines changed

include/swift/Basic/Sanitizers.def

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@
2020

2121
// SANITIZER(enum_bit, kind, name, file)
2222

23-
SANITIZER(0, Address, address, asan)
24-
SANITIZER(1, Thread, thread, tsan)
25-
SANITIZER(2, Undefined, undefined, ubsan)
26-
SANITIZER(3, Fuzzer, fuzzer, fuzzer)
27-
SANITIZER(4, Scudo, scudo, scudo_standalone)
23+
SANITIZER(0, Address, address, asan)
24+
SANITIZER(1, Thread, thread, tsan)
25+
SANITIZER(2, Undefined, undefined, ubsan)
26+
SANITIZER(3, Fuzzer, fuzzer, fuzzer)
27+
SANITIZER(4, Scudo, scudo, scudo_standalone)
28+
SANITIZER(5, MemTagStack, memtag-stack, memtag-stack)
2829

2930
#undef SANITIZER

lib/IRGen/IRGen.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,11 @@ swift::getIRTargetOptions(const IRGenOptions &Opts, ASTContext &Ctx,
189189
}
190190

191191
clang::TargetOptions &ClangOpts = Clang->getTargetInfo().getTargetOpts();
192+
193+
// Add +mte target feature when memtag-stack sanitizer is enabled
194+
if (Opts.Sanitizers & SanitizerKind::MemTagStack)
195+
ClangOpts.Features.push_back("+mte");
196+
192197
return std::make_tuple(TargetOpts, ClangOpts.CPU, ClangOpts.Features, ClangOpts.Triple);
193198
}
194199

lib/IRGen/IRGenSIL.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1907,6 +1907,8 @@ IRGenSILFunction::IRGenSILFunction(IRGenModule &IGM, SILFunction *f,
19071907
// being in the external file or via annotations.
19081908
if (IGM.IRGen.Opts.Sanitizers & SanitizerKind::Address)
19091909
CurFn->addFnAttr(llvm::Attribute::SanitizeAddress);
1910+
if (IGM.IRGen.Opts.Sanitizers & SanitizerKind::MemTagStack)
1911+
CurFn->addFnAttr(llvm::Attribute::SanitizeMemTag);
19101912
if (IGM.IRGen.Opts.Sanitizers & SanitizerKind::Thread) {
19111913
auto declContext = f->getDeclContext();
19121914
if (isa_and_nonnull<DestructorDecl>(declContext)) {

lib/Option/SanitizerOptions.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,11 @@ OptionSet<SanitizerKind> swift::parseSanitizerArgValues(
152152
bool isShared = (kind != SanitizerKind::Fuzzer);
153153
bool sanitizerSupported = sanitizerRuntimeLibExists(fileName, isShared);
154154

155+
if (kind == SanitizerKind::MemTagStack)
156+
// MemTagStack requires no runtime, so ignore library check above
157+
sanitizerSupported =
158+
Triple.isOSDarwin() && Triple.getArch() == llvm::Triple::aarch64;
159+
155160
// TSan is explicitly not supported for 32 bits.
156161
if (kind == SanitizerKind::Thread && !Triple.isArch64Bit())
157162
sanitizerSupported = false;
@@ -176,6 +181,18 @@ OptionSet<SanitizerKind> swift::parseSanitizerArgValues(
176181
Triple.getTriple());
177182
}
178183

184+
// MemTagStack and ASan can not be enabled concurrently.
185+
if ((sanitizerSet & SanitizerKind::MemTagStack)
186+
&& (sanitizerSet & SanitizerKind::Address)) {
187+
SmallString<128> b1;
188+
SmallString<128> b2;
189+
Diags.diagnose(SourceLoc(), diag::error_argument_not_allowed_with,
190+
(A->getOption().getPrefixedName()
191+
+ toStringRef(SanitizerKind::Address)).toStringRef(b1),
192+
(A->getOption().getPrefixedName()
193+
+ toStringRef(SanitizerKind::MemTagStack)).toStringRef(b2));
194+
}
195+
179196
// Address and thread sanitizers can not be enabled concurrently.
180197
if ((sanitizerSet & SanitizerKind::Thread)
181198
&& (sanitizerSet & SanitizerKind::Address)) {

test/Driver/sanitizers.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,21 @@
3939
// RUN: %swiftc_driver -sdk '""' -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=undefined -target x86_64-unknown-linux-gnu %s 2>&1 | %FileCheck -check-prefix=UBSAN_LINUX %s
4040
// RUN: %swiftc_driver -sdk '""' -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=undefined -target x86_64-unknown-windows-msvc %s 2>&1 | %FileCheck -check-prefix=UBSAN_WINDOWS %s
4141

42+
/*
43+
* MemTagStack Sanitizer Tests
44+
*/
45+
// RUN: %swiftc_driver -sdk '""' -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=memtag-stack -target arm64-apple-macosx10.9 %s 2>&1 | %FileCheck -check-prefix=MEMTAGSAN -check-prefix=MEMTAGSAN_OSX_ARM64 %s
46+
// RUN: not %swiftc_driver -sdk '""' -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=memtag-stack -target x86_64-apple-macosx10.9 %s 2>&1 | %FileCheck -check-prefix=MEMTAGSAN_OSX_X86 %s
47+
// RUN: not %swiftc_driver -sdk '""' -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=memtag-stack -target x86-apple-macosx10.9 %s 2>&1 | %FileCheck -check-prefix=MEMTAGSAN_OSX_32 %s
48+
// RUN: not %swiftc_driver -sdk '""' -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=memtag-stack -target x86_64-apple-ios7.1-simulator %s 2>&1 | %FileCheck -check-prefix=MEMTAGSAN_IOSSIM %s
49+
// RUN: %swiftc_driver -sdk '""' -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=memtag-stack -target arm64-apple-ios7.1 %s 2>&1 | %FileCheck -check-prefix=MEMTAGSAN_IOS %s
50+
// RUN: not %swiftc_driver -sdk '""' -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=memtag-stack -target x86_64-apple-tvos9.0-simulator %s 2>&1 | %FileCheck -check-prefix=MEMTAGSAN_tvOS_SIM %s
51+
// RUN: %swiftc_driver -sdk '""' -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=memtag-stack -target arm64-apple-tvos9.0 %s 2>&1 | %FileCheck -check-prefix=MEMTAGSAN_tvOS %s
52+
// RUN: not %swiftc_driver -sdk '""' -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=memtag-stack -target i386-apple-watchos2.0-simulator %s 2>&1 | %FileCheck -check-prefix=MEMTAGSAN_watchOS_SIM %s
53+
// RUN: not %swiftc_driver -sdk '""' -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=memtag-stack -target armv7k-apple-watchos2.0 %s 2>&1 | %FileCheck -check-prefix=MEMTAGSAN_watchOS %s
54+
// RUN: not %swiftc_driver -sdk '""' -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=memtag-stack -target x86_64-unknown-windows-msvc %s 2>&1 | %FileCheck -check-prefix=MEMTAGSAN_WINDOWS %s
55+
// RUN: not %swiftc_driver -sdk '""' -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=memtag-stack -target x86_64-unknown-linux-gnu %s 2>&1 | %FileCheck -check-prefix=MEMTAGSAN_LINUX %s
56+
4257
/*
4358
* Multiple Sanitizers At Once
4459
*/
@@ -50,6 +65,7 @@
5065
// RUN: not %swiftc_driver -sdk '""' -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -target x86_64-apple-macosx10.9 -sanitize=address,unknown %s 2>&1 | %FileCheck -check-prefix=BADARG %s
5166
// RUN: not %swiftc_driver -sdk '""' -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -target x86_64-apple-macosx10.9 -sanitize=address -sanitize=unknown %s 2>&1 | %FileCheck -check-prefix=BADARG %s
5267
// RUN: not %swiftc_driver -sdk '""' -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -target x86_64-apple-macosx10.9 -sanitize=address,thread %s 2>&1 | %FileCheck -check-prefix=INCOMPATIBLESANITIZERS %s
68+
// RUN: not %swiftc_driver -sdk '""' -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -target arm64-apple-macosx10.9 -sanitize=memtag-stack,address %s 2>&1 | %FileCheck -check-prefix=INCOMPATIBLESANITIZERS_2 %s
5369

5470
/*
5571
* Make sure we don't accidentally add the sanitizer library path when building libraries or modules
@@ -106,7 +122,23 @@
106122

107123
// UBSAN: -rpath @executable_path
108124

125+
// MEMTAGSAN: swift
126+
// MEMTAGSAN: -sanitize=memtag-stack
127+
128+
// MEMTAGSAN_OSX_ARM64-NOT: unsupported option '-sanitize=memtag-stack' for target 'arm64-apple-macosx10.9'
129+
// MEMTAGSAN_OSX_X86: unsupported option '-sanitize=memtag-stack' for target 'x86_64-apple-macosx10.9'
130+
// MEMTAGSAN_OSX_32: unsupported option '-sanitize=memtag-stack' for target 'x86-apple-macosx10.9'
131+
// MEMTAGSAN_IOSSIM: unsupported option '-sanitize=memtag-stack' for target 'x86_64-apple-ios7.1-simulator'
132+
// MEMTAGSAN_IOS-NOT: unsupported option '-sanitize=memtag-stack' for target 'arm64-apple-ios7.1'
133+
// MEMTAGSAN_tvOS_SIM: unsupported option '-sanitize=memtag-stack' for target 'x86_64-apple-tvos9.0-simulator'
134+
// MEMTAGSAN_tvOS-NOT: unsupported option '-sanitize=memtag-stack' for target 'arm64-apple-tvos9.0'
135+
// MEMTAGSAN_watchOS_SIM: unsupported option '-sanitize=memtag-stack' for target 'i386-apple-watchos2.0-simulator'
136+
// MEMTAGSAN_watchOS: unsupported option '-sanitize=memtag-stack' for target 'armv7k-apple-watchos2.0'
137+
// MEMTAGSAN_LINUX: unsupported option '-sanitize=memtag-stack' for target 'x86_64-unknown-linux-gnu'
138+
// MEMTAGSAN_WINDOWS: unsupported option '-sanitize=memtag-stack' for target 'x86_64-unknown-windows-msvc'
139+
109140
// MULTIPLE_SAN_LINUX: -fsanitize=address,undefined,fuzzer
110141

111142
// BADARG: unsupported argument 'unknown' to option '-sanitize='
112143
// INCOMPATIBLESANITIZERS: argument '-sanitize=address' is not allowed with '-sanitize=thread'
144+
// INCOMPATIBLESANITIZERS_2: argument '-sanitize=address' is not allowed with '-sanitize=memtag-stack'

test/IRGen/memtag_stack.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// REQUIRES: CODEGENERATOR=AArch64
2+
// REQUIRES: OS=macosx
3+
4+
// RUN: %swift -emit-ir -sanitize=memtag-stack -parse-as-library -target arm64-apple-macosx10.9 %s | %FileCheck %s
5+
6+
// Check that functions have the sanitize_memtag attribute when -sanitize=memtag-stack is enabled
7+
8+
// CHECK-LABEL: define {{.*}} @"${{.*}}testFunction{{.*}}"
9+
// CHECK-SAME: [[ATTRS:#[0-9]+]]
10+
// CHECK: attributes [[ATTRS]] = {{.*}} sanitize_memtag
11+
12+
func testFunction() -> Int {
13+
return 42
14+
}

0 commit comments

Comments
 (0)