From 14ce567fa267cce9466354bed1549a83286866b1 Mon Sep 17 00:00:00 2001 From: Weining Lu Date: Thu, 29 Dec 2022 11:37:46 +0800 Subject: [PATCH] [DFSan] Add `zeroext` attribute for callbacks with 8bit shadow variable arguments Add `zeroext` attribute for below callbacks' first parameter (8bit shadow variable arguments) to conform to many platforms' ABI calling convention and some compiler behavior. - __dfsan_load_callback - __dfsan_store_callback - __dfsan_cmp_callback - __dfsan_conditional_callback - __dfsan_conditional_callback_origin - __dfsan_reaches_function_callback - __dfsan_reaches_function_callback_origin The type of these callbacks' first parameter is u8 (see the definition of `dfsan_label`). First, many platforms' ABI requires unsigned integer data types (except unsigned int) are zero-extended when stored in general-purpose register. Second, the problem is that compiler optimization may assume the arguments are zero-extended and, if not, misbehave, e.g. it uses an `i8` argument to index into a jump table. If the argument has non-zero high bits, the output executable may crash at run-time. So we need to add the `zeroext` attribute when declaring and calling them. Reviewed By: browneee, MaskRay Differential Revision: https://reviews.llvm.org/D140689 --- .../Instrumentation/DataFlowSanitizer.cpp | 83 ++++++++++++++++------ .../Instrumentation/DataFlowSanitizer/array.ll | 8 +-- .../Instrumentation/DataFlowSanitizer/basic.ll | 6 +- .../Instrumentation/DataFlowSanitizer/callback.ll | 17 +++-- .../DataFlowSanitizer/reaches_function.ll | 2 +- .../Instrumentation/DataFlowSanitizer/struct.ll | 4 +- 6 files changed, 83 insertions(+), 37 deletions(-) diff --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp index d589624..f4964df 100644 --- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -1033,13 +1033,15 @@ void DFSanFunction::addConditionalCallbacksIfEnabled(Instruction &I, } IRBuilder<> IRB(&I); Value *CondShadow = getShadow(Condition); + CallInst *CI; if (DFS.shouldTrackOrigins()) { Value *CondOrigin = getOrigin(Condition); - IRB.CreateCall(DFS.DFSanConditionalCallbackOriginFn, - {CondShadow, CondOrigin}); + CI = IRB.CreateCall(DFS.DFSanConditionalCallbackOriginFn, + {CondShadow, CondOrigin}); } else { - IRB.CreateCall(DFS.DFSanConditionalCallbackFn, {CondShadow}); + CI = IRB.CreateCall(DFS.DFSanConditionalCallbackFn, {CondShadow}); } + CI->addParamAttr(0, Attribute::ZExt); } void DFSanFunction::addReachesFunctionCallbacksIfEnabled(IRBuilder<> &IRB, @@ -1078,6 +1080,7 @@ void DFSanFunction::addReachesFunctionCallbacksIfEnabled(IRBuilder<> &IRB, args = { DataShadow, FilePathPtr, CILine, FunctionNamePtr }; CB = IRB.CreateCall(DFS.DFSanReachesFunctionCallbackFn, args); } + CB->addParamAttr(0, Attribute::ZExt); CB->setDebugLoc(dbgloc); } @@ -1413,25 +1416,53 @@ void DataFlowSanitizer::initializeRuntimeFunctions(Module &M) { // Initializes event callback functions and declare them in the module void DataFlowSanitizer::initializeCallbackFunctions(Module &M) { - DFSanLoadCallbackFn = Mod->getOrInsertFunction("__dfsan_load_callback", - DFSanLoadStoreCallbackFnTy); - DFSanStoreCallbackFn = Mod->getOrInsertFunction("__dfsan_store_callback", - DFSanLoadStoreCallbackFnTy); + { + AttributeList AL; + AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt); + DFSanLoadCallbackFn = Mod->getOrInsertFunction( + "__dfsan_load_callback", DFSanLoadStoreCallbackFnTy, AL); + } + { + AttributeList AL; + AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt); + DFSanStoreCallbackFn = Mod->getOrInsertFunction( + "__dfsan_store_callback", DFSanLoadStoreCallbackFnTy, AL); + } DFSanMemTransferCallbackFn = Mod->getOrInsertFunction( "__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy); - DFSanCmpCallbackFn = - Mod->getOrInsertFunction("__dfsan_cmp_callback", DFSanCmpCallbackFnTy); - - DFSanConditionalCallbackFn = Mod->getOrInsertFunction( - "__dfsan_conditional_callback", DFSanConditionalCallbackFnTy); - DFSanConditionalCallbackOriginFn = - Mod->getOrInsertFunction("__dfsan_conditional_callback_origin", - DFSanConditionalCallbackOriginFnTy); - DFSanReachesFunctionCallbackFn = Mod->getOrInsertFunction( - "__dfsan_reaches_function_callback", DFSanReachesFunctionCallbackFnTy); - DFSanReachesFunctionCallbackOriginFn = - Mod->getOrInsertFunction("__dfsan_reaches_function_callback_origin", - DFSanReachesFunctionCallbackOriginFnTy); + { + AttributeList AL; + AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt); + DFSanCmpCallbackFn = Mod->getOrInsertFunction("__dfsan_cmp_callback", + DFSanCmpCallbackFnTy, AL); + } + { + AttributeList AL; + AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt); + DFSanConditionalCallbackFn = Mod->getOrInsertFunction( + "__dfsan_conditional_callback", DFSanConditionalCallbackFnTy, AL); + } + { + AttributeList AL; + AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt); + DFSanConditionalCallbackOriginFn = + Mod->getOrInsertFunction("__dfsan_conditional_callback_origin", + DFSanConditionalCallbackOriginFnTy, AL); + } + { + AttributeList AL; + AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt); + DFSanReachesFunctionCallbackFn = + Mod->getOrInsertFunction("__dfsan_reaches_function_callback", + DFSanReachesFunctionCallbackFnTy, AL); + } + { + AttributeList AL; + AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt); + DFSanReachesFunctionCallbackOriginFn = + Mod->getOrInsertFunction("__dfsan_reaches_function_callback_origin", + DFSanReachesFunctionCallbackOriginFnTy, AL); + } } void DataFlowSanitizer::injectMetadataGlobals(Module &M) { @@ -2403,7 +2434,9 @@ void DFSanVisitor::visitLoadInst(LoadInst &LI) { if (ClEventCallbacks) { IRBuilder<> IRB(Pos); Value *Addr8 = IRB.CreateBitCast(LI.getPointerOperand(), DFSF.DFS.Int8Ptr); - IRB.CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr8}); + CallInst *CI = + IRB.CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr8}); + CI->addParamAttr(0, Attribute::ZExt); } IRBuilder<> IRB(AfterLi); @@ -2663,7 +2696,9 @@ void DFSanVisitor::visitStoreInst(StoreInst &SI) { if (ClEventCallbacks) { IRBuilder<> IRB(&SI); Value *Addr8 = IRB.CreateBitCast(SI.getPointerOperand(), DFSF.DFS.Int8Ptr); - IRB.CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr8}); + CallInst *CI = + IRB.CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr8}); + CI->addParamAttr(0, Attribute::ZExt); } } @@ -2725,7 +2760,9 @@ void DFSanVisitor::visitCmpInst(CmpInst &CI) { if (ClEventCallbacks) { IRBuilder<> IRB(&CI); Value *CombinedShadow = DFSF.getShadow(&CI); - IRB.CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow); + CallInst *CallI = + IRB.CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow); + CallI->addParamAttr(0, Attribute::ZExt); } } diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/array.ll b/llvm/test/Instrumentation/DataFlowSanitizer/array.ll index e253871..c8c93ef 100644 --- a/llvm/test/Instrumentation/DataFlowSanitizer/array.ll +++ b/llvm/test/Instrumentation/DataFlowSanitizer/array.ll @@ -81,7 +81,7 @@ define [1 x i1] @load_array1(ptr %p) { ; EVENT_CALLBACKS: @load_array1.dfsan ; EVENT_CALLBACKS: [[L:%.*]] = or i[[#SBITS]] - ; EVENT_CALLBACKS: call void @__dfsan_load_callback(i[[#SBITS]] [[L]], ptr {{.*}}) + ; EVENT_CALLBACKS: call void @__dfsan_load_callback(i[[#SBITS]] zeroext [[L]], ptr {{.*}}) ; FAST: @load_array1.dfsan ; FAST: [[P:%.*]] = load i[[#SBITS]], ptr @__dfsan_arg_tls, align [[ALIGN:2]] @@ -107,7 +107,7 @@ define [2 x i1] @load_array2(ptr %p) { ; EVENT_CALLBACKS: @load_array2.dfsan ; EVENT_CALLBACKS: [[O1:%.*]] = or i[[#SBITS]] ; EVENT_CALLBACKS: [[O2:%.*]] = or i[[#SBITS]] [[O1]] - ; EVENT_CALLBACKS: call void @__dfsan_load_callback(i[[#SBITS]] [[O2]], ptr {{.*}}) + ; EVENT_CALLBACKS: call void @__dfsan_load_callback(i[[#SBITS]] zeroext [[O2]], ptr {{.*}}) ; FAST: @load_array2.dfsan ; FAST: [[P:%.*]] = load i[[#SBITS]], ptr @__dfsan_arg_tls, align [[ALIGN:2]] @@ -134,7 +134,7 @@ define [4 x i1] @load_array4(ptr %p) { ; EVENT_CALLBACKS: [[O1:%.*]] = or i[[#mul(4, SBITS)]] [[O0]] ; EVENT_CALLBACKS: [[O2:%.*]] = trunc i[[#mul(4, SBITS)]] [[O1]] to i[[#SBITS]] ; EVENT_CALLBACKS: [[O3:%.*]] = or i[[#SBITS]] [[O2]] - ; EVENT_CALLBACKS: call void @__dfsan_load_callback(i[[#SBITS]] [[O3]], ptr {{.*}}) + ; EVENT_CALLBACKS: call void @__dfsan_load_callback(i[[#SBITS]] zeroext [[O3]], ptr {{.*}}) ; FAST: @load_array4.dfsan ; FAST: [[T:%.*]] = trunc i[[#mul(4, SBITS)]] {{.*}} to i[[#SBITS]] @@ -196,7 +196,7 @@ define void @store_zero_array(ptr %p) { define void @store_array2([2 x i1] %a, ptr %p) { ; EVENT_CALLBACKS: @store_array2.dfsan ; EVENT_CALLBACKS: [[E12:%.*]] = or i[[#SBITS]] - ; EVENT_CALLBACKS: call void @__dfsan_store_callback(i[[#SBITS]] [[E12]], ptr %p) + ; EVENT_CALLBACKS: call void @__dfsan_store_callback(i[[#SBITS]] zeroext [[E12]], ptr %p) ; FAST: @store_array2.dfsan ; FAST: [[S:%.*]] = load [2 x i[[#SBITS]]], ptr @__dfsan_arg_tls, align [[ALIGN:2]] diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/basic.ll b/llvm/test/Instrumentation/DataFlowSanitizer/basic.ll index 1890053..567a512 100644 --- a/llvm/test/Instrumentation/DataFlowSanitizer/basic.ll +++ b/llvm/test/Instrumentation/DataFlowSanitizer/basic.ll @@ -30,10 +30,10 @@ define void @store(ptr %p) { ret void } -; CHECK: declare void @__dfsan_load_callback(i[[#SBITS]], ptr) -; CHECK: declare void @__dfsan_store_callback(i[[#SBITS]], ptr) +; CHECK: declare void @__dfsan_load_callback(i[[#SBITS]] zeroext, ptr) +; CHECK: declare void @__dfsan_store_callback(i[[#SBITS]] zeroext, ptr) ; CHECK: declare void @__dfsan_mem_transfer_callback(ptr, i64) -; CHECK: declare void @__dfsan_cmp_callback(i[[#SBITS]]) +; CHECK: declare void @__dfsan_cmp_callback(i[[#SBITS]] zeroext) ; CHECK: ; Function Attrs: nounwind memory(read) ; CHECK-NEXT: declare zeroext i[[#SBITS]] @__dfsan_union_load(ptr, i64) diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/callback.ll b/llvm/test/Instrumentation/DataFlowSanitizer/callback.ll index 19b7f2e..4bd8e7b 100644 --- a/llvm/test/Instrumentation/DataFlowSanitizer/callback.ll +++ b/llvm/test/Instrumentation/DataFlowSanitizer/callback.ll @@ -6,7 +6,7 @@ target triple = "x86_64-unknown-linux-gnu" ; CHECK: @__dfsan_shadow_width_bytes = weak_odr constant i32 [[#SBYTES:]] define i8 @load8(ptr %p) { - ; CHECK: call void @__dfsan_load_callback(i[[#SBITS]] %[[LABEL:.*]], ptr %p) + ; CHECK: call void @__dfsan_load_callback(i[[#SBITS]] zeroext %[[LABEL:.*]], ptr %p) ; CHECK: %a = load i8, ptr %p ; CHECK: store i[[#SBITS]] %[[LABEL]], ptr @__dfsan_retval_tls @@ -16,7 +16,7 @@ define i8 @load8(ptr %p) { define void @store8(ptr %p, i8 %a) { ; CHECK: store i[[#SBITS]] %[[LABEL:.*]], ptr %{{.*}} - ; CHECK: call void @__dfsan_store_callback(i[[#SBITS]] %[[LABEL]], ptr %p) + ; CHECK: call void @__dfsan_store_callback(i[[#SBITS]] zeroext %[[LABEL]], ptr %p) ; CHECK: store i8 %a, ptr %p store i8 %a, ptr %p @@ -24,10 +24,19 @@ define void @store8(ptr %p, i8 %a) { } define i1 @cmp(i8 %a, i8 %b) { - ; CHECK: call void @__dfsan_cmp_callback(i[[#SBITS]] %[[CMPLABEL:.*]]) + ; CHECK: call void @__dfsan_cmp_callback(i[[#SBITS]] zeroext %[[CMPLABEL:.*]]) ; CHECK: %c = icmp ne i8 %a, %b ; CHECK: store i[[#SBITS]] %[[CMPLABEL]], ptr @__dfsan_retval_tls %c = icmp ne i8 %a, %b ret i1 %c -} \ No newline at end of file +} + +; CHECK: declare void @__dfsan_load_callback(i[[#SBITS]] zeroext, ptr) +; CHECK: declare void @__dfsan_store_callback(i[[#SBITS]] zeroext, ptr) +; CHECK: declare void @__dfsan_mem_transfer_callback(ptr, i64) +; CHECK: declare void @__dfsan_cmp_callback(i[[#SBITS]] zeroext) +; CHECK: declare void @__dfsan_conditional_callback(i[[#SBITS]] zeroext) +; CHECK: declare void @__dfsan_conditional_callback_origin(i[[#SBITS]] zeroext, i32) +; CHECK: declare void @__dfsan_reaches_function_callback(i[[#SBITS]] zeroext, ptr, i32, ptr) +; CHECK: declare void @__dfsan_reaches_function_callback_origin(i[[#SBITS]] zeroext, i32, ptr, i32, ptr) diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/reaches_function.ll b/llvm/test/Instrumentation/DataFlowSanitizer/reaches_function.ll index 6546968..9e47795e 100644 --- a/llvm/test/Instrumentation/DataFlowSanitizer/reaches_function.ll +++ b/llvm/test/Instrumentation/DataFlowSanitizer/reaches_function.ll @@ -26,4 +26,4 @@ define void @call() { ret void } -; CHECK-LABEL: @__dfsan_reaches_function_callback(i8, ptr, i32, ptr) +; CHECK-LABEL: @__dfsan_reaches_function_callback(i8 zeroext, ptr, i32, ptr) diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/struct.ll b/llvm/test/Instrumentation/DataFlowSanitizer/struct.ll index cdb8c30..08e2fc6 100644 --- a/llvm/test/Instrumentation/DataFlowSanitizer/struct.ll +++ b/llvm/test/Instrumentation/DataFlowSanitizer/struct.ll @@ -133,7 +133,7 @@ define {i1, i1} @load_struct(ptr %p) { ; EVENT_CALLBACKS: [[OL0:%.*]] = or i[[#SBITS]] ; EVENT_CALLBACKS: [[OL1:%.*]] = or i[[#SBITS]] [[OL0]], ; EVENT_CALLBACKS: [[S0:%.*]] = insertvalue { i[[#SBITS]], i[[#SBITS]] } undef, i[[#SBITS]] [[OL1]], 0 - ; EVENT_CALLBACKS: call void @__dfsan_load_callback(i[[#SBITS]] [[OL1]] + ; EVENT_CALLBACKS: call void @__dfsan_load_callback(i[[#SBITS]] zeroext [[OL1]] %s = load {i1, i1}, ptr %p ret {i1, i1} %s @@ -152,7 +152,7 @@ define void @store_struct(ptr %p, {i1, i1} %s) { ; EVENT_CALLBACKS: @store_struct.dfsan ; EVENT_CALLBACKS: [[OL:%.*]] = or i[[#SBITS]] - ; EVENT_CALLBACKS: call void @__dfsan_store_callback(i[[#SBITS]] [[OL]] + ; EVENT_CALLBACKS: call void @__dfsan_store_callback(i[[#SBITS]] zeroext [[OL]] ; COMBINE_STORE_PTR: @store_struct.dfsan ; COMBINE_STORE_PTR: [[PL:%.*]] = load i[[#SBITS]], ptr @__dfsan_arg_tls, align [[ALIGN:2]] -- 2.7.4