diff --git a/compiler-rt/lib/msan/msan_interceptors.cpp b/compiler-rt/lib/msan/msan_interceptors.cpp --- a/compiler-rt/lib/msan/msan_interceptors.cpp +++ b/compiler-rt/lib/msan/msan_interceptors.cpp @@ -1543,6 +1543,11 @@ SetShadow(a, size, __msan::flags()->poison_stack_with_zeroes ? 0 : -1); } +void __msan_poison_stack_with_origin(void *a, uptr size, char *descr, uptr pc) { + __msan_poison_stack(a, size); + __msan_set_alloca_origin4(a, size, descr, pc); +} + void __msan_unpoison_param(uptr n) { UnpoisonParam(n); } void __msan_clear_and_unpoison(void *a, uptr size) { diff --git a/compiler-rt/lib/msan/msan_interface_internal.h b/compiler-rt/lib/msan/msan_interface_internal.h --- a/compiler-rt/lib/msan/msan_interface_internal.h +++ b/compiler-rt/lib/msan/msan_interface_internal.h @@ -88,6 +88,8 @@ void __msan_poison(const void *a, uptr size); SANITIZER_INTERFACE_ATTRIBUTE void __msan_poison_stack(void *a, uptr size); +SANITIZER_INTERFACE_ATTRIBUTE +void __msan_poison_stack_with_origin(void *a, uptr size, char *descr, uptr pc); // Copy size bytes from src to dst and unpoison the result. // Useful to implement unsafe loads. diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -565,8 +565,8 @@ /// allocation. FunctionCallee MsanSetAllocaOrigin4Fn; - /// Run-time helper that poisons stack on function entry. - FunctionCallee MsanPoisonStackFn; + /// Run-time helpers that poison stack on function entry. + FunctionCallee MsanPoisonStackFn, MsanPoisonStackWithOriginFn; /// Run-time helper that records a store (or any event) of an /// uninitialized value and returns an updated origin id encoding this info. @@ -837,6 +837,10 @@ MsanPoisonStackFn = M.getOrInsertFunction("__msan_poison_stack", IRB.getVoidTy(), IRB.getInt8PtrTy(), IntptrTy); + MsanPoisonStackWithOriginFn = + M.getOrInsertFunction("__msan_poison_stack_with_origin", IRB.getVoidTy(), + IRB.getInt8PtrTy(), IntptrTy, IRB.getInt8PtrTy(), + IntptrTy); } /// Insert extern declaration of runtime-provided functions and globals. @@ -3582,8 +3586,16 @@ void poisonAllocaUserspace(AllocaInst &I, IRBuilder<> &IRB, Value *Len) { if (PoisonStack && ClPoisonStackWithCall) { - IRB.CreateCall(MS.MsanPoisonStackFn, - {IRB.CreatePointerCast(&I, IRB.getInt8PtrTy()), Len}); + if (MS.TrackOrigins) { + Value *Descr = getLocalVarDescription(I); + IRB.CreateCall(MS.MsanPoisonStackWithOriginFn, + {IRB.CreatePointerCast(&I, IRB.getInt8PtrTy()), Len, + IRB.CreatePointerCast(Descr, IRB.getInt8PtrTy()), + IRB.CreatePointerCast(&F, MS.IntptrTy)}); + } else { + IRB.CreateCall(MS.MsanPoisonStackFn, + {IRB.CreatePointerCast(&I, IRB.getInt8PtrTy()), Len}); + } } else { Value *ShadowBase, *OriginBase; std::tie(ShadowBase, OriginBase) = getShadowOriginPtr( @@ -3592,14 +3604,14 @@ Value *PoisonValue = IRB.getInt8(PoisonStack ? ClPoisonStackPattern : 0); IRB.CreateMemSet(ShadowBase, PoisonValue, Len, MaybeAlign(I.getAlignment())); - } - if (PoisonStack && MS.TrackOrigins) { - Value *Descr = getLocalVarDescription(I); - IRB.CreateCall(MS.MsanSetAllocaOrigin4Fn, - {IRB.CreatePointerCast(&I, IRB.getInt8PtrTy()), Len, - IRB.CreatePointerCast(Descr, IRB.getInt8PtrTy()), - IRB.CreatePointerCast(&F, MS.IntptrTy)}); + if (PoisonStack && MS.TrackOrigins) { + Value *Descr = getLocalVarDescription(I); + IRB.CreateCall(MS.MsanSetAllocaOrigin4Fn, + {IRB.CreatePointerCast(&I, IRB.getInt8PtrTy()), Len, + IRB.CreatePointerCast(Descr, IRB.getInt8PtrTy()), + IRB.CreatePointerCast(&F, MS.IntptrTy)}); + } } } diff --git a/llvm/test/Instrumentation/MemorySanitizer/alloca.ll b/llvm/test/Instrumentation/MemorySanitizer/alloca.ll --- a/llvm/test/Instrumentation/MemorySanitizer/alloca.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/alloca.ll @@ -1,15 +1,23 @@ ; RUN: opt < %s -msan-check-access-address=0 -S -passes=msan 2>&1 | FileCheck \ ; RUN: %s "--check-prefixes=CHECK,INLINE" ; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck %s --check-prefixes=CHECK,INLINE + ; RUN: opt < %s -msan-check-access-address=0 -msan-poison-stack-with-call=1 -S \ ; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,CALL" ; RUN: opt < %s -msan -msan-check-access-address=0 -msan-poison-stack-with-call=1 -S | FileCheck %s --check-prefixes=CHECK,CALL + +; RUN: opt < %s -msan-check-access-address=0 -msan-poison-stack-with-call=1 \ +; RUN: -msan-track-origins=1 -S -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,CALL-ORIGIN" +; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=1 \ +; RUN: -msan-poison-stack-with-call=1 -S | FileCheck %s --check-prefixes=CHECK,CALL-ORIGIN + ; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S \ -; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,ORIGIN" -; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=1 -S | FileCheck %s --check-prefixes=CHECK,ORIGIN +; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,INLINE,ORIGIN" +; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=1 -S | FileCheck %s --check-prefixes=CHECK,INLINE,ORIGIN ; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=2 -S \ -; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,ORIGIN" -; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=2 -S | FileCheck %s --check-prefixes=CHECK,ORIGIN +; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,INLINE,ORIGIN" +; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=2 -S | FileCheck %s --check-prefixes=CHECK,INLINE,ORIGIN + ; RUN: opt < %s -S -passes="msan" 2>&1 | FileCheck %s \ ; RUN: "--check-prefixes=CHECK,KMSAN" ; RUN: opt < %s -msan-kernel=1 -S -passes=msan 2>&1 | FileCheck %s \ @@ -28,6 +36,7 @@ ; CHECK-LABEL: define void @static( ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) +; CALL-ORIGIN: call void @__msan_poison_stack_with_origin(i8* {{.*}}, i64 4 ; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: ret void @@ -44,6 +53,7 @@ ; CHECK-LABEL: define void @dynamic( ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) +; CALL-ORIGIN: call void @__msan_poison_stack_with_origin(i8* {{.*}}, i64 4 ; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: ret void @@ -57,6 +67,7 @@ ; CHECK-LABEL: define void @array( ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 20, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 20) +; CALL-ORIGIN: call void @__msan_poison_stack_with_origin(i8* {{.*}}, i64 20 ; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 20, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 20, ; CHECK: ret void @@ -71,6 +82,7 @@ ; CHECK: %[[A:.*]] = mul i64 4, %cnt ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 %[[A]], i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 %[[A]]) +; CALL-ORIGIN: call void @__msan_poison_stack_with_origin(i8* {{.*}}, i64 %[[A]] ; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 %[[A]], ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 %[[A]], ; CHECK: ret void @@ -85,6 +97,7 @@ ; CHECK-LABEL: define void @unpoison_local( ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 0, i64 20, i1 false) ; CALL: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 0, i64 20, i1 false) +; CALL-ORIGIN-NOT: call void @__msan_poison_stack_with_origin(i8* {{.*}}, i64 20 ; ORIGIN-NOT: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 20, ; KMSAN: call void @__msan_unpoison_alloca(i8* {{.*}}, i64 20) ; CHECK: ret void @@ -114,12 +127,14 @@ ; CHECK: call void @llvm.lifetime.start ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) +; CALL-ORIGIN: call void @__msan_poison_stack_with_origin(i8* {{.*}}, i64 4 ; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: call void @llvm.lifetime.start ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) +; CALL-ORIGIN: call void @__msan_poison_stack_with_origin(i8* {{.*}}, i64 4 ; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: ret void @@ -141,6 +156,7 @@ ; CHECK: %[[A:.*]] = mul i64 4, %cnt ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 %[[A]], i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 %[[A]]) +; CALL-ORIGIN: call void @__msan_poison_stack_with_origin(i8* {{.*}}, i64 %[[A]] ; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 %[[A]], ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 %[[A]], ; CHECK: call void @llvm.lifetime.end @@ -181,22 +197,26 @@ ; CHECK: %x = alloca i32 ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) +; CALL-ORIGIN: call void @__msan_poison_stack_with_origin(i8* {{.*}}, i64 4 ; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: %y = alloca i32 ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) +; CALL-ORIGIN: call void @__msan_poison_stack_with_origin(i8* {{.*}}, i64 4 ; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: %z = alloca i32 ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) +; CALL-ORIGIN: call void @__msan_poison_stack_with_origin(i8* {{.*}}, i64 4 ; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; There're two lifetime intrinsics for %z, but we must instrument it only once. ; INLINE-NOT: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL-NOT: call void @__msan_poison_stack(i8* {{.*}}, i64 4) +; CALL-ORIGIN-NOT: call void @__msan_poison_stack_with_origin(i8* {{.*}}, i64 4 ; ORIGIN-NOT: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, ; KMSAN-NOT: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK-LABEL: another_bb: @@ -204,12 +224,14 @@ ; CHECK: call void @llvm.lifetime.start ; INLINE-NOT: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL-NOT: call void @__msan_poison_stack(i8* {{.*}}, i64 4) +; CALL-ORIGIN-NOT: call void @__msan_poison_stack_with_origin(i8* {{.*}}, i64 4 ; ORIGIN-NOT: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, ; KMSAN-NOT: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: call void @llvm.lifetime.end ; CHECK: call void @llvm.lifetime.start ; INLINE-NOT: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL-NOT: call void @__msan_poison_stack(i8* {{.*}}, i64 4) +; CALL-ORIGIN-NOT: call void @__msan_poison_stack_with_origin(i8* {{.*}}, i64 4 ; ORIGIN-NOT: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, ; KMSAN-NOT: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: call void @llvm.lifetime.end