Skip to content

[sanitizer] Lift AsanDoesNotSupportStaticLinkage to sanitizer_common.h. NFC #80948

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

MaskRay
Copy link
Member

@MaskRay MaskRay commented Feb 7, 2024

The _DYNAMIC reference from AsanDoesNotSupportStaticLinkage ensures
that clang++ -fsanitize=address -static gets a linker error.
MemprofDoesNotSupportStaticLinkage is similar for -fmemory-profile.
Move the functions to sanitizer_common.h to be used by more sanitizers
on ELF platforms.

Fuchsia does not use interposition and opts out the check (its
AsanDoesNotSupportStaticLinkage is a no-op).

Created using spr 1.3.4
@llvmbot llvmbot added compiler-rt compiler-rt:asan Address sanitizer PGO Profile Guided Optimizations compiler-rt:sanitizer labels Feb 7, 2024
@llvmbot
Copy link
Member

llvmbot commented Feb 7, 2024

@llvm/pr-subscribers-pgo

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Fangrui Song (MaskRay)

Changes

The _DYNAMIC reference from AsanDoesNotSupportStaticLinkage ensures
that clang++ -fsanitize=address -static gets a linker error. Move the
function to sanitizer_common.h to be used by more sanitizers on ELF
platforms.

Fuchsia opts out the check as its AsanDoesNotSupportStaticLinkage is a
no-op.


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

10 Files Affected:

  • (modified) compiler-rt/lib/asan/asan_fuchsia.cpp (-2)
  • (modified) compiler-rt/lib/asan/asan_internal.h (-1)
  • (modified) compiler-rt/lib/asan/asan_linux.cpp (-7)
  • (modified) compiler-rt/lib/asan/asan_mac.cpp (-5)
  • (modified) compiler-rt/lib/asan/asan_rtl.cpp (+2-3)
  • (modified) compiler-rt/lib/asan/asan_win.cpp (-2)
  • (modified) compiler-rt/lib/memprof/memprof_internal.h (-1)
  • (modified) compiler-rt/lib/memprof/memprof_linux.cpp (-7)
  • (modified) compiler-rt/lib/memprof/memprof_rtl.cpp (+1-1)
  • (modified) compiler-rt/lib/sanitizer_common/sanitizer_common.h (+11)
diff --git a/compiler-rt/lib/asan/asan_fuchsia.cpp b/compiler-rt/lib/asan/asan_fuchsia.cpp
index 12625e9d75833..dbc4342e83388 100644
--- a/compiler-rt/lib/asan/asan_fuchsia.cpp
+++ b/compiler-rt/lib/asan/asan_fuchsia.cpp
@@ -57,8 +57,6 @@ void AsanCheckDynamicRTPrereqs() {}
 void AsanCheckIncompatibleRT() {}
 void InitializeAsanInterceptors() {}
 
-void *AsanDoesNotSupportStaticLinkage() { return nullptr; }
-
 void InitializePlatformExceptionHandlers() {}
 void AsanOnDeadlySignal(int signo, void *siginfo, void *context) {
   UNIMPLEMENTED();
diff --git a/compiler-rt/lib/asan/asan_internal.h b/compiler-rt/lib/asan/asan_internal.h
index 2944ebe213b5d..06dfc4b177339 100644
--- a/compiler-rt/lib/asan/asan_internal.h
+++ b/compiler-rt/lib/asan/asan_internal.h
@@ -80,7 +80,6 @@ void ReplaceSystemMalloc();
 
 // asan_linux.cpp / asan_mac.cpp / asan_win.cpp
 uptr FindDynamicShadowStart();
-void *AsanDoesNotSupportStaticLinkage();
 void AsanCheckDynamicRTPrereqs();
 void AsanCheckIncompatibleRT();
 
diff --git a/compiler-rt/lib/asan/asan_linux.cpp b/compiler-rt/lib/asan/asan_linux.cpp
index 37d3bad1b1ec6..cdc1912a6d832 100644
--- a/compiler-rt/lib/asan/asan_linux.cpp
+++ b/compiler-rt/lib/asan/asan_linux.cpp
@@ -51,11 +51,9 @@ extern "C" void *_DYNAMIC;
 #  elif SANITIZER_NETBSD
 #    include <link_elf.h>
 #    include <ucontext.h>
-extern Elf_Dyn _DYNAMIC;
 #  else
 #    include <link.h>
 #    include <sys/ucontext.h>
-extern ElfW(Dyn) _DYNAMIC[];
 #  endif
 
 typedef enum {
@@ -76,11 +74,6 @@ void InitializePlatformInterceptors() {}
 void InitializePlatformExceptionHandlers() {}
 bool IsSystemHeapAddress(uptr addr) { return false; }
 
-void *AsanDoesNotSupportStaticLinkage() {
-  // This will fail to link with -static.
-  return &_DYNAMIC;
-}
-
 #  if ASAN_PREMAP_SHADOW
 uptr FindPremappedShadowStart(uptr shadow_size_bytes) {
   uptr granularity = GetMmapGranularity();
diff --git a/compiler-rt/lib/asan/asan_mac.cpp b/compiler-rt/lib/asan/asan_mac.cpp
index 1b0e9b3fe0060..b250f796e165f 100644
--- a/compiler-rt/lib/asan/asan_mac.cpp
+++ b/compiler-rt/lib/asan/asan_mac.cpp
@@ -49,11 +49,6 @@ void InitializePlatformInterceptors() {}
 void InitializePlatformExceptionHandlers() {}
 bool IsSystemHeapAddress (uptr addr) { return false; }
 
-// No-op. Mac does not support static linkage anyway.
-void *AsanDoesNotSupportStaticLinkage() {
-  return 0;
-}
-
 uptr FindDynamicShadowStart() {
   return MapDynamicShadow(MemToShadowSize(kHighMemEnd), ASAN_SHADOW_SCALE,
                           /*min_shadow_base_alignment*/ 0, kHighMemEnd);
diff --git a/compiler-rt/lib/asan/asan_rtl.cpp b/compiler-rt/lib/asan/asan_rtl.cpp
index a61deed7382b0..dbfad57955c75 100644
--- a/compiler-rt/lib/asan/asan_rtl.cpp
+++ b/compiler-rt/lib/asan/asan_rtl.cpp
@@ -410,6 +410,8 @@ static bool AsanInitInternal() {
     return false;
   }
 
+  // Make sure we are not statically linked.
+  DoesNotSupportStaticLinking();
   AsanCheckIncompatibleRT();
   AsanCheckDynamicRTPrereqs();
   AvoidCVE_2016_2143();
@@ -421,9 +423,6 @@ static bool AsanInitInternal() {
 
   InitializeHighMemEnd();
 
-  // Make sure we are not statically linked.
-  AsanDoesNotSupportStaticLinkage();
-
   // Install tool-specific callbacks in sanitizer_common.
   AddDieCallback(AsanDie);
   SetCheckUnwindCallback(CheckUnwind);
diff --git a/compiler-rt/lib/asan/asan_win.cpp b/compiler-rt/lib/asan/asan_win.cpp
index 8507e675684ed..cda1f7a91e140 100644
--- a/compiler-rt/lib/asan/asan_win.cpp
+++ b/compiler-rt/lib/asan/asan_win.cpp
@@ -266,8 +266,6 @@ void PlatformTSDDtor(void *tsd) { AsanThread::TSDDtor(tsd); }
 // }}}
 
 // ---------------------- Various stuff ---------------- {{{
-void *AsanDoesNotSupportStaticLinkage() { return 0; }
-
 uptr FindDynamicShadowStart() {
   return MapDynamicShadow(MemToShadowSize(kHighMemEnd), ASAN_SHADOW_SCALE,
                           /*min_shadow_base_alignment*/ 0, kHighMemEnd);
diff --git a/compiler-rt/lib/memprof/memprof_internal.h b/compiler-rt/lib/memprof/memprof_internal.h
index 990e62ce1a55d..ad61d829d72ca 100644
--- a/compiler-rt/lib/memprof/memprof_internal.h
+++ b/compiler-rt/lib/memprof/memprof_internal.h
@@ -61,7 +61,6 @@ void ReplaceSystemMalloc();
 
 // memprof_linux.cpp
 uptr FindDynamicShadowStart();
-void *MemprofDoesNotSupportStaticLinkage();
 
 // memprof_thread.cpp
 MemprofThread *CreateMainThread();
diff --git a/compiler-rt/lib/memprof/memprof_linux.cpp b/compiler-rt/lib/memprof/memprof_linux.cpp
index fcb6f662a82e5..26a2b456b874e 100644
--- a/compiler-rt/lib/memprof/memprof_linux.cpp
+++ b/compiler-rt/lib/memprof/memprof_linux.cpp
@@ -38,8 +38,6 @@
 #include <unistd.h>
 #include <unwind.h>
 
-extern ElfW(Dyn) _DYNAMIC[];
-
 typedef enum {
   MEMPROF_RT_VERSION_UNDEFINED = 0,
   MEMPROF_RT_VERSION_DYNAMIC,
@@ -57,11 +55,6 @@ namespace __memprof {
 void InitializePlatformInterceptors() {}
 void InitializePlatformExceptionHandlers() {}
 
-void *MemprofDoesNotSupportStaticLinkage() {
-  // This will fail to link with -static.
-  return &_DYNAMIC;
-}
-
 uptr FindDynamicShadowStart() {
   uptr shadow_size_bytes = MemToShadowSize(kHighMemEnd);
   return MapDynamicShadow(shadow_size_bytes, SHADOW_SCALE,
diff --git a/compiler-rt/lib/memprof/memprof_rtl.cpp b/compiler-rt/lib/memprof/memprof_rtl.cpp
index 5e2e7bc2be3f7..83e377f8e4307 100644
--- a/compiler-rt/lib/memprof/memprof_rtl.cpp
+++ b/compiler-rt/lib/memprof/memprof_rtl.cpp
@@ -162,7 +162,7 @@ static void MemprofInitInternal() {
   InitializeHighMemEnd();
 
   // Make sure we are not statically linked.
-  MemprofDoesNotSupportStaticLinkage();
+  DoesNotSupportStaticLinking();
 
   // Install tool-specific callbacks in sanitizer_common.
   AddDieCallback(MemprofDie);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
index b99c0cffcbb11..999ddb2f82dbc 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
@@ -290,6 +290,17 @@ bool SetEnv(const char *name, const char *value);
 
 u32 GetUid();
 void ReExec();
+
+#if defined(__ELF__) && !SANITIZER_FUCHSIA
+extern uptr kDynamic[] asm("_DYNAMIC");
+inline void DoesNotSupportStaticLinking() {
+  // This will fail to link with -static. However, -static-pie is not detected.
+  [[maybe_unused]] volatile auto x = &kDynamic;
+}
+#else
+inline void DoesNotSupportStaticLinking() {}
+#endif
+
 void CheckASLR();
 void CheckMPROTECT();
 char **GetArgv();

@MaskRay MaskRay requested a review from teresajohnson February 7, 2024 07:45
@MaskRay
Copy link
Member Author

MaskRay commented Feb 7, 2024

Move the function to sanitizer_common.h to be used by more sanitizers on ELF platforms.

for msan/tsan/hwasan/lsan in a subsequent change. Currently statically linking them leads to an immediate segfault.

Copy link
Contributor

@teresajohnson teresajohnson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you update the description to note you are also removing the one from memprof?

#if defined(__ELF__) && !SANITIZER_FUCHSIA
extern uptr kDynamic[] asm("_DYNAMIC");
inline void DoesNotSupportStaticLinking() {
// This will fail to link with -static. However, -static-pie is not detected.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a TODO that should be added to detect -static-pie? How can that one be detected?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've clarified that we are unable to detect -static-pie at link time.

This is not a TODO, since there is no way to statically detect -static-pie.

@@ -290,6 +290,17 @@ bool SetEnv(const char *name, const char *value);

u32 GetUid();
void ReExec();

#if defined(__ELF__) && !SANITIZER_FUCHSIA
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does Fuchsia not want this checking?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

compiler-rt/lib/asan/asan_fuchsia.cpp has void *AsanDoesNotSupportStaticLinkage() { return nullptr; }, which opts out the check. I am not familiar with Fuchsia, but it doesn't seem to use interceptors, so technically static linking is supported, unlike other ELF OSes.

@petrhosek

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, it has no interceptors.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we hide that from header and move into .cpp file?

Copy link
Member Author

@MaskRay MaskRay Feb 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reference is intentionally in an inline function in the RTSanitizerCommon library, so that each client can decide whether they need the link-time guard: if the function is not called, there is no such check.

If we move it into .cpp, programs linking in ubsan/xray will fail for -static.

I think we can make ubsan standalone runtime work for -static: #80943
At the very least, we should not let -fsanitize-minimal-runtime fail for -static.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a separate header? It's not strong request.

Also should this rather be a part of /interception/ lib?

Copy link
Member Author

@MaskRay MaskRay Feb 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to compiler-rt/lib/interception/interception.h to make it clear -static unsupportness is due to interception.

@MaskRay
Copy link
Member Author

MaskRay commented Feb 12, 2024

@vitalybuka Does this look good now?

@MaskRay MaskRay merged commit 8443ce5 into main Feb 17, 2024
@MaskRay MaskRay deleted the users/MaskRay/spr/sanitizer-lift-asandoesnotsupportstaticlinkage-to-sanitizer_commonh-nfc branch February 17, 2024 03:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler-rt:asan Address sanitizer compiler-rt:sanitizer compiler-rt PGO Profile Guided Optimizations
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants