[llvm] ed5a349 - Make setSanitizerMetadata byval.

Mitch Phillips via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 16 14:47:51 PDT 2022


Author: Mitch Phillips
Date: 2022-06-16T14:47:27-07:00
New Revision: ed5a349b89e9ccc1c3dbe427de27d28e145f8203

URL: https://github.com/llvm/llvm-project/commit/ed5a349b89e9ccc1c3dbe427de27d28e145f8203
DIFF: https://github.com/llvm/llvm-project/commit/ed5a349b89e9ccc1c3dbe427de27d28e145f8203.diff

LOG: Make setSanitizerMetadata byval.

This fixes a UaF bug in llvm::GlobalObject::copyAttributesFrom, where a
sanitizer metadata object is captured by reference, and passed by
reference to llvm::GlobalValue::setSanitizerMetadata. The reference
comes from the same map that the new value is going to be inserted to,
and the map insertion triggers iterator invalidation - leading to a
use-after-free on the dangling reference.

This patch fixes that bug by making setSanitizerMetadata's argument
byval. This should also systematically prevent the problem from
happening in future, as it's a very easy pattern to have. This shouldn't
be any performance problem, the SanitizerMetadata struct is a bitfield
POD.

Added: 
    

Modified: 
    llvm/include/llvm/IR/GlobalValue.h
    llvm/lib/IR/Globals.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/GlobalValue.h b/llvm/include/llvm/IR/GlobalValue.h
index 0f901e0fca506..a17423dd965b7 100644
--- a/llvm/include/llvm/IR/GlobalValue.h
+++ b/llvm/include/llvm/IR/GlobalValue.h
@@ -324,7 +324,11 @@ class GlobalValue : public Constant {
 
   bool hasSanitizerMetadata() const { return HasSanitizerMetadata; }
   const SanitizerMetadata &getSanitizerMetadata() const;
-  void setSanitizerMetadata(const SanitizerMetadata &Meta);
+  // Note: Not byref as it's a POD and otherwise it's too easy to call
+  // G.setSanitizerMetadata(G2.getSanitizerMetadata()), and the argument becomes
+  // dangling when the backing storage allocates the metadata for `G`, as the
+  // storage is shared between `G1` and `G2`.
+  void setSanitizerMetadata(SanitizerMetadata Meta);
   void removeSanitizerMetadata();
 
   static LinkageTypes getLinkOnceLinkage(bool ODR) {

diff  --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp
index d2ddfd4d8a1e1..9f1ed1d4b120b 100644
--- a/llvm/lib/IR/Globals.cpp
+++ b/llvm/lib/IR/Globals.cpp
@@ -228,7 +228,7 @@ const SanitizerMetadata &GlobalValue::getSanitizerMetadata() const {
   return getContext().pImpl->GlobalValueSanitizerMetadata[this];
 }
 
-void GlobalValue::setSanitizerMetadata(const SanitizerMetadata &Meta) {
+void GlobalValue::setSanitizerMetadata(SanitizerMetadata Meta) {
   getContext().pImpl->GlobalValueSanitizerMetadata[this] = Meta;
   HasSanitizerMetadata = true;
 }


        


More information about the llvm-commits mailing list