From d76f9d742084bfb8b10a73a35864687934df9005 Mon Sep 17 00:00:00 2001 From: Antonio Frighetto Date: Fri, 13 Sep 2024 12:16:25 +0200 Subject: [PATCH] [Instrumentation] Do not run sanitizers for naked functions Sanitizers instrumentation is incompatible with naked functions, which are expected to contain only inline asm. --- .../Instrumentation/AddressSanitizer.cpp | 4 ++ .../Instrumentation/DataFlowSanitizer.cpp | 3 +- .../Instrumentation/MemorySanitizer.cpp | 4 ++ .../SanitizerBinaryMetadata.cpp | 3 ++ .../Instrumentation/SanitizerCoverage.cpp | 3 ++ .../Instrumentation/sanitizers-no-naked.ll | 49 +++++++++++++++++++ 6 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 llvm/test/Instrumentation/sanitizers-no-naked.ll diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp index 5de0a78d087968..1e9e2d03c6ce42 100644 --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -2960,6 +2960,10 @@ bool AddressSanitizer::instrumentFunction(Function &F, bool FunctionModified = false; + // Do not apply any instrumentation for naked functions. + if (F.hasFnAttribute(Attribute::Naked)) + return FunctionModified; + // If needed, insert __asan_init before checking for SanitizeAddress attr. // This function needs to be called even if the function body is not // instrumented. diff --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp index b4b5f67d2e62da..1cb579309089e1 100644 --- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -1545,8 +1545,9 @@ bool DataFlowSanitizer::runImpl( SmallPtrSet FnsWithForceZeroLabel; SmallPtrSet PersonalityFns; for (Function &F : M) + // Do not apply any instrumentation for naked functions or if disabled. if (!F.isIntrinsic() && !DFSanRuntimeFunctions.contains(&F) && - !LibAtomicFunction(F) && + !LibAtomicFunction(F) && !F.hasFnAttribute(Attribute::Naked) && !F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) { FnsToInstrument.push_back(&F); if (F.hasPersonalityFn()) diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index 17c5638cf8ced7..90de58143955c3 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -6078,6 +6078,10 @@ bool MemorySanitizer::sanitizeFunction(Function &F, TargetLibraryInfo &TLI) { if (!CompileKernel && F.getName() == kMsanModuleCtorName) return false; + // Do not apply any instrumentation for naked functions. + if (F.hasFnAttribute(Attribute::Naked)) + return false; + if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) return false; diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp index e326f30ad88eeb..eb346254f30dd7 100644 --- a/llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp +++ b/llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp @@ -258,6 +258,9 @@ bool SanitizerBinaryMetadata::run() { void SanitizerBinaryMetadata::runOn(Function &F, MetadataInfoSet &MIS) { if (F.empty()) return; + // Do not apply any instrumentation for naked functions. + if (F.hasFnAttribute(Attribute::Naked)) + return; if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) return; if (Ignorelist && Ignorelist->inSection("metadata", "fun", F.getName())) diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index 6a89cee9aaf6cc..db4bf709c9cc9c 100644 --- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -629,6 +629,9 @@ void ModuleSanitizerCoverage::instrumentFunction(Function &F) { return; if (Blocklist && Blocklist->inSection("coverage", "fun", F.getName())) return; + // Do not apply any instrumentation for naked functions. + if (F.hasFnAttribute(Attribute::Naked)) + return; if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return; if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) diff --git a/llvm/test/Instrumentation/sanitizers-no-naked.ll b/llvm/test/Instrumentation/sanitizers-no-naked.ll new file mode 100644 index 00000000000000..72a78d9f1a33e5 --- /dev/null +++ b/llvm/test/Instrumentation/sanitizers-no-naked.ll @@ -0,0 +1,49 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt < %s -passes=asan -S | FileCheck %s +; RUN: opt < %s -passes=tsan -S | FileCheck %s +; RUN: opt < %s -passes=dfsan -dfsan-track-origins=1 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-control-flow -S | FileCheck %s +; RUN: opt < %s -passes='module(sanmd-module)' -sanitizer-metadata-atomics -S | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @naked_function() naked { +; CHECK-LABEL: define void @naked_function( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: call void asm sideeffect "nop", ""() +; CHECK-NEXT: unreachable +; + call void asm sideeffect "nop", ""() + unreachable +} + +define void @naked_function_with_asan() sanitize_address naked { +; CHECK-LABEL: define void @naked_function_with_asan( +; CHECK-SAME: ) #[[ATTR1:[0-9]+]] { +; CHECK-NEXT: call void asm sideeffect "nop", ""() +; CHECK-NEXT: unreachable +; + call void asm sideeffect "nop", ""() + unreachable +} + +define void @naked_function_with_tsan() sanitize_thread naked { +; CHECK-LABEL: define void @naked_function_with_tsan( +; CHECK-SAME: ) #[[ATTR2:[0-9]+]] { +; CHECK-NEXT: call void asm sideeffect "nop", ""() +; CHECK-NEXT: unreachable +; + call void asm sideeffect "nop", ""() + unreachable +} + +define void @naked_function_with_msan() sanitize_memory naked { +; CHECK-LABEL: define void @naked_function_with_msan( +; CHECK-SAME: ) #[[ATTR3:[0-9]+]] { +; CHECK-NEXT: call void asm sideeffect "nop", ""() +; CHECK-NEXT: unreachable +; + call void asm sideeffect "nop", ""() + unreachable +}