[llvm] [asan][x86] Abort instrumenting memintrinsics that target fs, gs (PR #129291)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 28 14:16:09 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Thor Preimesberger (cheezeburglar)
<details>
<summary>Changes</summary>
For #<!-- -->124238
Currently code such as
```
#include "stdint.h"
void test(uintptr_t addr) {
__builtin_memcpy(( void __seg_fs*)addr, "x", 1);
}
```
and
```
...
call void @<!-- -->llvm.memcpy.p257.p0.i64(ptr addrspace(257) align 1 %4, ptr align 1 @.str, i64 1, i1 false)
...
```
are miscompiled by ASan. When any of mem{set, cpy, move} are intercepted, by ASan, the writes to fs and gs are effectively scrubbed from the calls to ASan's runtime. This commit just causes AddressSanitizer to bail when on instrumenting these sorts of memory intrinsics.
(Really sorry if you got pinged accidentally when I was editing the commit history before - my bad)
---
Full diff: https://github.com/llvm/llvm-project/pull/129291.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp (+12)
- (added) llvm/test/Instrumentation/AddressSanitizer/X86/bug_124238.ll (+60)
``````````diff
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index 8d8d56035a48f..85edcb1276efe 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -797,6 +797,7 @@ struct AddressSanitizer {
bool IsWrite, size_t AccessSizeIndex,
Value *SizeArgument, uint32_t Exp,
RuntimeCallInserter &RTCI);
+ bool maybeIgnoreMemIntrinsic(MemIntrinsic *MI, const Triple &TargetTriple);
void instrumentMemIntrinsic(MemIntrinsic *MI, RuntimeCallInserter &RTCI);
Value *memToShadow(Value *Shadow, IRBuilder<> &IRB);
bool suppressInstrumentationSiteForDebug(int &Instrumented);
@@ -1340,10 +1341,21 @@ Value *AddressSanitizer::memToShadow(Value *Shadow, IRBuilder<> &IRB) {
return IRB.CreateAdd(Shadow, ShadowBase);
}
+bool AddressSanitizer::maybeIgnoreMemIntrinsic(MemIntrinsic *MI,
+ const Triple &TargetTriple) {
+ // Ignore FS and GS registers to prevent miscompilation
+ if (MI->getDestAddressSpace() >= 256 &&
+ TargetTriple.getArch() == Triple::x86_64)
+ return true;
+ return false;
+}
+
// Instrument memset/memmove/memcpy
void AddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI,
RuntimeCallInserter &RTCI) {
InstrumentationIRBuilder IRB(MI);
+ if (maybeIgnoreMemIntrinsic(MI, TargetTriple))
+ return;
if (isa<MemTransferInst>(MI)) {
RTCI.createRuntimeCall(
IRB, isa<MemMoveInst>(MI) ? AsanMemmove : AsanMemcpy,
diff --git a/llvm/test/Instrumentation/AddressSanitizer/X86/bug_124238.ll b/llvm/test/Instrumentation/AddressSanitizer/X86/bug_124238.ll
new file mode 100644
index 0000000000000..ce82bc48563a0
--- /dev/null
+++ b/llvm/test/Instrumentation/AddressSanitizer/X86/bug_124238.ll
@@ -0,0 +1,60 @@
+; RUN: opt -passes=asan %s -S | FileCheck %s
+
+;; Punt AddressSanitizer::instrumentMemIntrinsics out for MemIntrinsics
+;; that need write to unsupported registers on X86
+;; PR124238: https://www.github.com/llvm/llvm-project/issues/124238
+
+target triple = "x86_64-unknown-linux-gnu"
+
+$.str.658906a285b7a0f82dabd9915e07848c = comdat any
+ at .str = internal constant { [2 x i8], [30 x i8] } { [2 x i8] c"x\00", [30 x i8] zeroinitializer }, comdat($.str.658906a285b7a0f82dabd9915e07848c), align 32
+ at 0 = private alias { [2 x i8], [30 x i8] }, ptr @.str
+
+define void @test_memcpy(i64 noundef %addr) sanitize_address #0 {
+entry:
+ %addr.addr = alloca i64, align 8
+ store i64 %addr, ptr %addr.addr, align 8
+ %0 = load i64, ptr %addr.addr, align 8
+ %1 = inttoptr i64 %0 to ptr addrspace(257)
+ call void @llvm.memcpy.p257.p0.i64(ptr addrspace(257) align 1 %1, ptr align 1 @.str, i64 1, i1 false)
+; CHECK: llvm.memcpy
+ %2 = load i64, ptr %addr.addr, align 8
+ %3 = inttoptr i64 %2 to ptr addrspace(256)
+ call void @llvm.memcpy.p256.p0.i64(ptr addrspace(256) align 1 %3, ptr align 1 @.str, i64 1, i1 false)
+; CHECK: llvm.memcpy
+ ret void
+}
+
+define void @test_memset(i64 noundef %addr) sanitize_address #0 {
+entry:
+ %addr.addr = alloca i64, align 8
+ store i64 %addr, ptr %addr.addr, align 8
+ %0 = load i64, ptr %addr.addr, align 8
+ %1 = inttoptr i64 %0 to ptr addrspace(257)
+ call void @llvm.memset.p257.i64(ptr addrspace(257) align 1 %1, i8 0, i64 1, i1 false)
+; CHECK: llvm.memset
+ %2 = load i64, ptr %addr.addr, align 8
+ %3 = inttoptr i64 %2 to ptr addrspace(256)
+ call void @llvm.memset.p256.i64(ptr addrspace(256) align 1 %3, i8 0, i64 1, i1 false)
+; CHECK: llvm.memset
+ ret void
+}
+
+define void @test_memmove(i64 noundef %addr) sanitize_address #0 {
+entry:
+ %addr.addr = alloca i64, align 8
+ store i64 %addr, ptr %addr.addr, align 8
+ %0 = load i64, ptr %addr.addr, align 8
+ %1 = inttoptr i64 %0 to ptr addrspace(257)
+ %2 = load i64, ptr %addr.addr, align 8
+ %3 = inttoptr i64 %2 to ptr
+ call void @llvm.memmove.p257.p0.i64(ptr addrspace(257) align 1 %1, ptr align 1 %3, i64 1, i1 false)
+; CHECK: llvm.memmove
+ %4 = load i64, ptr %addr.addr, align 8
+ %5 = inttoptr i64 %4 to ptr addrspace(256)
+ %6 = load i64, ptr %addr.addr, align 8
+ %7 = inttoptr i64 %6 to ptr
+ call void @llvm.memmove.p256.p0.i64(ptr addrspace(256) align 1 %5, ptr align 1 %7, i64 1, i1 false)
+; CHECK: llvm.memmove
+ ret void
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/129291
More information about the llvm-commits
mailing list