Issue 146679
Summary [asan][win] The memory used for PoisonShadow should be created
Labels new issue
Assignees
Reporter GkvJwa
    Here is a [issue](https://github.com/llvm/llvm-project/issues/144355) on Win


Because the memory is not created when running to ```FastPoisonShadow->memset```, an access violation will be triggered under the debugger

As mentioned in the issue, msvc's asan does not have this problem, So I analyzed the asan version of msvc, there is indeed a big difference

The memory for ```PoisonShadow``` will be created
```
void __fastcall __asan::AsanMapUnmapCallback::OnMap(
 __asan::AsanMapUnmapCallback *this,
        unsigned __int64 p,
 unsigned __int64 size)
{
  __asan::AsanStats *CurrentThreadStats; // rax

  _sanitizer_virtual_alloc(
    (char *)_asan_shadow_memory_dynamic_address + (p >> 3),
    (unsigned __int64)_asan_shadow_memory_dynamic_address
  + ((size + p - 8) >> 3)
  - ((_QWORD)_asan_shadow_memory_dynamic_address
   + (p >> 3))
  + 1,
 0x1000u,
    4u);
  __asan::PoisonShadow(p, size, 0xFAu);
 CurrentThreadStats = __asan::GetCurrentThreadStats();
 ++CurrentThreadStats->mmaps;
  CurrentThreadStats->mmaped += size;
}

-->

void AsanMapUnmapCallback::OnMap(uptr p, uptr size) const {
  uptr shadow_beg = MEM_TO_SHADOW(p);
  uptr shadow_end = MEM_TO_SHADOW(p + size - ASAN_SHADOW_GRANULARITY) + 1;

  VirtualAlloc((LPVOID)shadow_beg, shadow_end - shadow_beg, MEM_COMMIT,
               PAGE_READWRITE);
 PoisonShadow(p, size, kAsanHeapLeftRedzoneMagic);
  // Statistics.
 AsanStats &thread_stats = GetCurrentThreadStats();
  thread_stats.mmaps++;
 thread_stats.mmaped += size;
}
```
To avoid exceptions in debugger

Of course, MSVC's ASAN also has many other logics
like
When calling PoisonShadow, _sanitizer_virtual_alloc is basically executed first
```
void __fastcall __asan::AsanThread::ClearShadowForThreadStackAndTLS(__asan::AsanThread *this)
{
  unsigned __int64 stack_bottom; // rax
  unsigned __int64 stack_top; // r8
  unsigned __int64 tls_end; // rax
  unsigned __int64 tls_begin; // rdi
  unsigned __int64 v6; // rdi
  unsigned __int64 v7; // rbx

  stack_bottom = this->stack_bottom_;
  stack_top = this->stack_top_;
  if ( stack_top != stack_bottom )
  {
 _sanitizer_virtual_alloc(
      (char *)_asan_shadow_memory_dynamic_address + (stack_bottom >> 3),
      (unsigned __int64)_asan_shadow_memory_dynamic_address
    + ((stack_top - 8) >> 3)
 - ((_QWORD)_asan_shadow_memory_dynamic_address
     + (stack_bottom >> 3))
    + 1,
      0x1000u,
      4u);
 __asan::PoisonShadow(this->stack_bottom_, this->stack_top_ - this->stack_bottom_, 0);
  }
  tls_end = this->tls_end_;
```

rewritten VirtualAlloc
```
void *__fastcall _sanitizer_virtual_alloc(
        void *lpAddress,
        unsigned __int64 dwSize,
        unsigned int flAllocationType,
        unsigned int flProtect)
{
  void *v5; // [rsp+40h] [rbp+8h] BYREF
  unsigned __int64 v6; // [rsp+48h] [rbp+10h] BYREF
  unsigned int v7; // [rsp+50h] [rbp+18h] BYREF
  unsigned int v8; // [rsp+58h] [rbp+20h] BYREF

  v8 = flProtect;
  v7 = flAllocationType;
 v6 = dwSize;
  v5 = lpAddress;
  return __sanitizer::IATOverwriteGuard<void * (void *,unsigned __int64,unsigned long,unsigned long),void * &,unsigned __int64 &,unsigned long &,unsigned long &>(
           "VirtualAlloc IAT entry overwritten.",
           (void *(__fastcall *)(void *, unsigned __int64, unsigned int, unsigned int))VirtualAlloc,
           &v5,
 &v6,
           &v7,
           &v8);
}
```

Therefore, it may be better for asan to create the memory for PoisonShadow in advance on the windows, like MSVC does.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to