[llvm] [LLVM][rtsan] Add `sanitize_realtime_unsafe` attribute (PR #106754)

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 30 09:11:28 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-ir

Author: None (davidtrevelyan)

<details>
<summary>Changes</summary>

# Introducing `sanitize_realtime_unsafe` attribute

## Motivation

Calls to system library functions such as `malloc` are easy for RealtimeSanitizer to intercept. If such a call is made in a `[[clang::nonblocking]]` function (a real-time context), RealtimeSanitizer will error. Real-time programmers also write their own blocking (real-time unsafe) functions that may or may not call intercepted functions. We wish to introduce a mechanism whereby RealtimeSanitizer can error on calls to these, too, if called within a real-time context.

## Implementation

At the same time as introducing `[[clang::nonblocking]]`, the `[[clang::blocking]]` attribute was also introduced. With the performance constraints attribute warnings (as errors) activated, blocking functions cannot be called from non-blocking functions, and this is enforced at compile time. The purpose of this PR is to introduce similar functionality into RealtimeSanitizer, so that it can make the equivalent check at run time.

Using the same mechanism as adding the `sanitize_realtime` LLVM function attribute to the IR of `[[clang::nonblocking]]` functions, we wish to add the `sanitize_realtime_unsafe` attribute. If this attribute is detected, the RealtimeSanitizer pass inserts a call to `__rtsan_expect_not_realtime`.

## Integration Roadmap

The above functionality is currently split into two patches.

- [ ] Introduction of the `sanitize_realtime_unsafe` LLVM attribute (this PR), and
- [ ] An update to RealtimeSanitizer's LLVM pass to use it.


---
Full diff: https://github.com/llvm/llvm-project/pull/106754.diff


10 Files Affected:

- (modified) llvm/docs/LangRef.rst (+5) 
- (modified) llvm/include/llvm/Bitcode/LLVMBitCodes.h (+1) 
- (modified) llvm/include/llvm/IR/Attributes.td (+5) 
- (modified) llvm/lib/Bitcode/Reader/BitcodeReader.cpp (+2) 
- (modified) llvm/lib/Bitcode/Writer/BitcodeWriter.cpp (+2) 
- (modified) llvm/lib/IR/Verifier.cpp (+6) 
- (modified) llvm/lib/Transforms/Utils/CodeExtractor.cpp (+1) 
- (modified) llvm/test/Bitcode/attributes.ll (+6) 
- (modified) llvm/test/Bitcode/compatibility.ll (+6-2) 
- (added) llvm/test/Verifier/rtsan-attrs.ll (+9) 


``````````diff
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index c75b75edaf2ca0..05bd962fa5dd14 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -2315,6 +2315,11 @@ example:
     This attribute indicates that RealtimeSanitizer checks
     (realtime safety analysis - no allocations, syscalls or exceptions) are enabled
     for this function.
+``sanitize_realtime_unsafe``
+    This attribute indicates that RealtimeSanitizer should error immediately
+    if the attributed function is called during invocation of a function
+    attributed with ``sanitize_realtime``.
+    This attribute is incompatible with the ``sanitize_realtime`` attribute.
 ``speculative_load_hardening``
     This attribute indicates that
     `Speculative Load Hardening <https://llvm.org/docs/SpeculativeLoadHardening.html>`_
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index 4beac37a583445..47d86a4725d909 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -759,6 +759,7 @@ enum AttributeKindCodes {
   ATTR_KIND_INITIALIZES = 94,
   ATTR_KIND_HYBRID_PATCHABLE = 95,
   ATTR_KIND_SANITIZE_REALTIME = 96,
+  ATTR_KIND_SANITIZE_REALTIME_UNSAFE = 97,
 };
 
 enum ComdatSelectionKindCodes {
diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td
index 891e34fec0c798..eeea5b02ad2ced 100644
--- a/llvm/include/llvm/IR/Attributes.td
+++ b/llvm/include/llvm/IR/Attributes.td
@@ -300,6 +300,10 @@ def SanitizeNumericalStability : EnumAttr<"sanitize_numerical_stability", [FnAtt
 /// RealtimeSanitizer is on.
 def SanitizeRealtime : EnumAttr<"sanitize_realtime", [FnAttr]>;
 
+/// RealtimeSanitizer should error if a real-time unsafe function is invoked
+/// during a real-time sanitized function (see `sanitize_realtime`).
+def SanitizeRealtimeUnsafe : EnumAttr<"sanitize_realtime_unsafe", [FnAttr]>;
+
 /// Speculative Load Hardening is enabled.
 ///
 /// Note that this uses the default compatibility (always compatible during
@@ -389,6 +393,7 @@ def : CompatRule<"isEqual<SanitizeHWAddressAttr>">;
 def : CompatRule<"isEqual<SanitizeMemTagAttr>">;
 def : CompatRule<"isEqual<SanitizeNumericalStabilityAttr>">;
 def : CompatRule<"isEqual<SanitizeRealtimeAttr>">;
+def : CompatRule<"isEqual<SanitizeRealtimeUnsafeAttr>">;
 def : CompatRule<"isEqual<SafeStackAttr>">;
 def : CompatRule<"isEqual<ShadowCallStackAttr>">;
 def : CompatRule<"isEqual<UseSampleProfileAttr>">;
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 654be985a3229c..aa74a5abe9d0ec 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -2143,6 +2143,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
     return Attribute::SanitizeNumericalStability;
   case bitc::ATTR_KIND_SANITIZE_REALTIME:
     return Attribute::SanitizeRealtime;
+  case bitc::ATTR_KIND_SANITIZE_REALTIME_UNSAFE:
+    return Attribute::SanitizeRealtimeUnsafe;
   case bitc::ATTR_KIND_SPECULATIVE_LOAD_HARDENING:
     return Attribute::SpeculativeLoadHardening;
   case bitc::ATTR_KIND_SWIFT_ERROR:
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 26fd02b3e1a043..152293509dbb77 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -845,6 +845,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
     return bitc::ATTR_KIND_SANITIZE_NUMERICAL_STABILITY;
   case Attribute::SanitizeRealtime:
     return bitc::ATTR_KIND_SANITIZE_REALTIME;
+  case Attribute::SanitizeRealtimeUnsafe:
+    return bitc::ATTR_KIND_SANITIZE_REALTIME_UNSAFE;
   case Attribute::SpeculativeLoadHardening:
     return bitc::ATTR_KIND_SPECULATIVE_LOAD_HARDENING;
   case Attribute::SwiftError:
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index d8f3bab45b2a65..449d871576763f 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -2223,6 +2223,12 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs,
           "Attributes 'optdebug and optnone' are incompatible!", V);
   }
 
+  Check(!(Attrs.hasFnAttr(Attribute::SanitizeRealtime) &&
+          Attrs.hasFnAttr(Attribute::SanitizeRealtimeUnsafe)),
+        "Attributes "
+        "'sanitize_realtime and sanitize_realtime_unsafe' are incompatible!",
+        V);
+
   if (Attrs.hasFnAttr(Attribute::OptimizeForDebugging)) {
     Check(!Attrs.hasFnAttr(Attribute::OptimizeForSize),
           "Attributes 'optsize and optdebug' are incompatible!", V);
diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp
index d378c6c3a4b01c..a60d70244110d4 100644
--- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp
+++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp
@@ -951,6 +951,7 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs,
       case Attribute::SanitizeHWAddress:
       case Attribute::SanitizeMemTag:
       case Attribute::SanitizeRealtime:
+      case Attribute::SanitizeRealtimeUnsafe:
       case Attribute::SpeculativeLoadHardening:
       case Attribute::StackProtect:
       case Attribute::StackProtectReq:
diff --git a/llvm/test/Bitcode/attributes.ll b/llvm/test/Bitcode/attributes.ll
index 4402289ac170d9..a66eda19ff5735 100644
--- a/llvm/test/Bitcode/attributes.ll
+++ b/llvm/test/Bitcode/attributes.ll
@@ -511,6 +511,11 @@ define void @f92() sanitize_realtime
         ret void;
 }
 
+; CHECK: define void @f93() #54
+define void @f93() sanitize_realtime_unsafe {
+        ret void;
+}
+
 ; CHECK: define void @f87() [[FNRETTHUNKEXTERN:#[0-9]+]]
 define void @f87() fn_ret_thunk_extern { ret void }
 
@@ -606,6 +611,7 @@ define void @initializes(ptr initializes((-4, 0), (4, 8)) %a) {
 ; CHECK: attributes #51 = { uwtable(sync) }
 ; CHECK: attributes #52 = { nosanitize_bounds }
 ; CHECK: attributes #53 = { sanitize_realtime }
+; CHECK: attributes #54 = { sanitize_realtime_unsafe }
 ; CHECK: attributes [[FNRETTHUNKEXTERN]] = { fn_ret_thunk_extern }
 ; CHECK: attributes [[SKIPPROFILE]] = { skipprofile }
 ; CHECK: attributes [[OPTDEBUG]] = { optdebug }
diff --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll
index fd60c49a4be39b..35c43b7d09446e 100644
--- a/llvm/test/Bitcode/compatibility.ll
+++ b/llvm/test/Bitcode/compatibility.ll
@@ -1562,7 +1562,7 @@ exit:
   ; CHECK: select <2 x i1> <i1 true, i1 false>, <2 x i8> <i8 2, i8 3>, <2 x i8> <i8 3, i8 2>
 
   call void @f.nobuiltin() builtin
-  ; CHECK: call void @f.nobuiltin() #53
+  ; CHECK: call void @f.nobuiltin() #54
 
   call fastcc noalias ptr @f.noalias() noinline
   ; CHECK: call fastcc noalias ptr @f.noalias() #12
@@ -1992,6 +1992,9 @@ declare void @f.sanitize_numerical_stability() sanitize_numerical_stability
 declare void @f.sanitize_realtime() sanitize_realtime
 ; CHECK: declare void @f.sanitize_realtime() #52
 
+declare void @f.sanitize_realtime_unsafe() sanitize_realtime_unsafe
+; CHECK: declare void @f.sanitize_realtime_unsafe() #53
+
 ; CHECK: declare nofpclass(snan) float @nofpclass_snan(float nofpclass(snan))
 declare nofpclass(snan) float @nofpclass_snan(float nofpclass(snan))
 
@@ -2115,7 +2118,8 @@ define float @nofpclass_callsites(float %arg) {
 ; CHECK: attributes #50 = { allockind("alloc,uninitialized") }
 ; CHECK: attributes #51 = { sanitize_numerical_stability }
 ; CHECK: attributes #52 = { sanitize_realtime }
-; CHECK: attributes #53 = { builtin }
+; CHECK: attributes #53 = { sanitize_realtime_unsafe }
+; CHECK: attributes #54 = { builtin }
 
 ;; Metadata
 
diff --git a/llvm/test/Verifier/rtsan-attrs.ll b/llvm/test/Verifier/rtsan-attrs.ll
new file mode 100644
index 00000000000000..fcc44d8d63c1de
--- /dev/null
+++ b/llvm/test/Verifier/rtsan-attrs.ll
@@ -0,0 +1,9 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: Attributes 'sanitize_realtime and sanitize_realtime_unsafe' are incompatible!
+; CHECK-NEXT: ptr @sanitize_unsafe
+define void @sanitize_unsafe() #0 {
+  ret void
+}
+
+attributes #0 = { sanitize_realtime sanitize_realtime_unsafe }

``````````

</details>


https://github.com/llvm/llvm-project/pull/106754


More information about the llvm-commits mailing list