From 8c1506c9289afbb1a3eda8d9a2cf80c374b1ceb8 Mon Sep 17 00:00:00 2001 From: Gui Andrade Date: Thu, 23 Jul 2020 16:36:19 +0000 Subject: [PATCH] [MSAN] Never allow checking calls to __sanitizer_unaligned_{load,store} These functions expect the caller to always pass shadows over TLS. Differential Revision: https://reviews.llvm.org/D84351 --- .../Instrumentation/MemorySanitizer.cpp | 10 +++++-- .../MemorySanitizer/no-check-rt-unaligned.ll | 30 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 test/Instrumentation/MemorySanitizer/no-check-rt-unaligned.ll diff --git a/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/lib/Transforms/Instrumentation/MemorySanitizer.cpp index 0001559c405..10e104c9922 100644 --- a/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -3551,6 +3551,12 @@ struct MemorySanitizerVisitor : public InstVisitor { maybeMarkSanitizerLibraryCallNoBuiltin(Call, TLI); } IRBuilder<> IRB(&CB); + bool MayCheckCall = ClEagerChecks; + if (Function *Func = CB.getCalledFunction()) { + // __sanitizer_unaligned_{load,store} functions may be called by users + // and always expects shadows in the TLS. So don't check them. + MayCheckCall &= !Func->getName().startswith("__sanitizer_unaligned_"); + } unsigned ArgOffset = 0; LLVM_DEBUG(dbgs() << " CallSite: " << CB << "\n"); @@ -3576,7 +3582,7 @@ struct MemorySanitizerVisitor : public InstVisitor { bool ByVal = CB.paramHasAttr(i, Attribute::ByVal); bool NoUndef = CB.paramHasAttr(i, Attribute::NoUndef); - bool EagerCheck = ClEagerChecks && !ByVal && NoUndef; + bool EagerCheck = MayCheckCall && !ByVal && NoUndef; if (EagerCheck) { insertShadowCheck(A, &CB); @@ -3632,7 +3638,7 @@ struct MemorySanitizerVisitor : public InstVisitor { if (isa(CB) && cast(CB).isMustTailCall()) return; - if (ClEagerChecks && CB.hasRetAttr(Attribute::NoUndef)) { + if (MayCheckCall && CB.hasRetAttr(Attribute::NoUndef)) { setShadow(&CB, getCleanShadow(&CB)); setOrigin(&CB, getCleanOrigin()); return; diff --git a/test/Instrumentation/MemorySanitizer/no-check-rt-unaligned.ll b/test/Instrumentation/MemorySanitizer/no-check-rt-unaligned.ll new file mode 100644 index 00000000000..971d5c38811 --- /dev/null +++ b/test/Instrumentation/MemorySanitizer/no-check-rt-unaligned.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -msan-eager-checks -msan-check-access-address=0 -S -passes=msan 2>&1 | FileCheck %s +; RUN: opt < %s -msan-eager-checks -msan-check-access-address=0 -msan-track-origins=2 -S -passes=msan 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-ORIGIN +; RUN: opt < %s -msan-eager-checks -msan -msan-check-access-address=0 -S | FileCheck %s +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare noundef i8 @__sanitizer_unaligned_load8(i8* noundef) +declare void @__sanitizer_unaligned_store8(i8* noundef, i8 noundef) + +define noundef i8 @unaligned_load(i8* noundef %ptr) sanitize_memory { +; CHECK: @unaligned_load(i8* {{.*}}[[PTR:%.+]]) +; CHECK: store i64 0, {{.*}} @__msan_param_tls +; CHECK: [[VAL:%.*]] = call noundef i8 @__sanitizer_unaligned_load8(i8* noundef [[PTR]]) + %val = call noundef i8 @__sanitizer_unaligned_load8(i8* noundef %ptr) +; CHECK: load {{.*}} @__msan_retval_tls +; CHECK-ORIGIN: load {{.*}} @__msan_retval_origin_tls +; CHECK: call void @__msan_warning_{{.*}}noreturn +; CHECK: ret i8 [[VAL]] + ret i8 %val +} + +define void @unaligned_store(i8* noundef %ptr, i8 noundef %val) sanitize_memory { +; CHECK: @unaligned_store(i8* {{.*}}[[PTR:%.+]], i8 {{.*}}[[VAL:%.+]]) +; CHECK: store i64 0, {{.*}} @__msan_param_tls +; CHECK: store i8 0, {{.*}} @__msan_param_tls +; CHECK: call void @__sanitizer_unaligned_store8(i8* noundef [[PTR]], i8 noundef [[VAL]]) + call void @__sanitizer_unaligned_store8(i8* noundef %ptr, i8 noundef %val) +; CHECK: ret void + ret void +}