LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 30903 - [ASan/Win] Ignore allocations that occur before the dynamic runtime is initialized
Summary: [ASan/Win] Ignore allocations that occur before the dynamic runtime is initia...
Status: RESOLVED FIXED
Alias: None
Product: compiler-rt
Classification: Unclassified
Component: compiler-rt (show other bugs)
Version: unspecified
Hardware: PC Windows NT
: P normal
Assignee: Unassigned LLVM Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-11-03 14:46 PDT by dmajor
Modified: 2016-11-15 09:59 PST (History)
3 users (show)

See Also:
Fixed By Commit(s):


Attachments
Rough draft of a patch (3.86 KB, patch)
2016-11-03 14:53 PDT, dmajor
Details

Note You need to log in before you can comment on or make changes to this bug.
Description dmajor 2016-11-03 14:46:23 PDT
$ echo "int main() { return 0; }" > test.cpp
$ clang-cl -MD -fsanitize=address test.cpp
$ test.exe
=================================================================
==9112==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x00bdaef0 in thread T0
    #0 0x650f6cca in free d:\src\llvm\projects\compiler-rt\lib\asan\asan_malloc_win.cc:77
    #1 0x74670ba1 in destroy_fls (C:\Windows\System32\ucrtbase.dll+0x10030ba1)
    #2 0x772a9ec2 in RtlProcessFlsData (C:\Windows\SYSTEM32\ntdll.dll+0x4b2a9ec2)
    #3 0x772aa142 in LdrShutdownProcess (C:\Windows\SYSTEM32\ntdll.dll+0x4b2aa142)
    #4 0x772a9d85 in RtlExitUserProcess (C:\Windows\SYSTEM32\ntdll.dll+0x4b2a9d85)
    #5 0x7702adc2 in ExitProcessImplementation (C:\Windows\System32\KERNEL32.DLL+0x6b82adc2)
    #6 0x746796a4 in exit_or_terminate_process (C:\Windows\System32\ucrtbase.dll+0x100396a4)
    #7 0x74679664 in common_exit (C:\Windows\System32\ucrtbase.dll+0x10039664)
    #8 0x74679600 in exit (C:\Windows\System32\ucrtbase.dll+0x10039600)
    #9 0xb01267 in _scrt_common_main_seh f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:260
    #10 0x770162c3 in BaseThreadInitThunk (C:\Windows\System32\KERNEL32.DLL+0x6b8162c3)
    #11 0x772e0718 in __RtlUserThreadStart (C:\Windows\SYSTEM32\ntdll.dll+0x4b2e0718)
    #12 0x772e06e3 in _RtlUserThreadStart (C:\Windows\SYSTEM32\ntdll.dll+0x4b2e06e3)

Address 0x00bdaef0 is a wild pointer.
SUMMARY: AddressSanitizer: bad-free d:\src\llvm\projects\compiler-rt\lib\asan\asan_malloc_win.cc:77 in free
==9112==ABORTING

That memory was allocated here, before the ASan runtime had an opportunity to set up interceptions:

ntdll!RtlAllocateHeap+0x32
ucrtbase!_calloc_base+0x37
ucrtbase!__acrt_initialize_ptd+0x5a
ucrtbase!__acrt_execute_initializers+0x5c
ucrtbase!DllMainProcessAttach+0x18
ucrtbase!DllMainDispatch+0x28b
ucrtbase!__acrt_DllMain+0x14
ntdll!LdrxCallInitRoutine+0x16
ntdll!LdrpCallInitRoutine+0x43
ntdll!LdrpInitializeNode+0x10e
ntdll!LdrpInitializeGraphRecurse+0x5d
ntdll!LdrpInitializeGraphRecurse+0x74
ntdll!LdrpInitializeGraphRecurse+0x74
ntdll!LdrpInitializeGraphRecurse+0x74
ntdll!LdrpInitializeProcess+0xc22
ntdll!_LdrpInitialize+0x178
ntdll!LdrInitializeThunk+0x10

I suspect that the only way to deal with these is to have free() ignore anything that belongs to the system heap.
Comment 1 dmajor 2016-11-03 14:53:09 PDT
Created attachment 17550 [details]
Rough draft of a patch

This has free() ignore anything that can be found by a HeapWalk, once we've started ExitProcess. It's working ok with the Firefox unit tests. I'm not sure if there's a better way to do this.
Comment 2 Reid Kleckner 2016-11-07 09:07:16 PST
I'm pretty sure your example won't repro for me, but I'll check when I get into work. Ettiene has encountered the same crash stack when using newer dbghelp.dll versions. I want to do two things:

1. Write a test that deterministically reproduces these results across Windows installations
2. Study it to see if we can get asan to initialize earlier than ucrtbase.dll so we don't miss these allocations

If 2 fails, then we can start trying to handle missed allocations, but I want to convince myself that we can't initialize earlier before going down that road.
Comment 3 dmajor 2016-11-07 09:28:31 PST
I agree that dealing with missed allocations is unfortunate, but I couldn't see any way around it. The allocation stack in comment 0 happens while the NT loader is traversing the dependency graph; ucrtbase.dll initializes before we even reach the entry point of clang_rt.asan_dynamic-i386.dll.

To run code any earlier would require either: (1) removing clang_rt.asan_dynamic-i386.dll's dependency on ucrtbase.dll, or (2) adding some new DLL that loads before clang_rt.asan_dynamic-i386.dll. Neither of those seem particularly great.

That said, if you can think of an option that I've overlooked, I'd be happy to hear it!
Comment 4 Reid Kleckner 2016-11-07 09:36:24 PST
My asan runtime doesn't depend on ucrtbase.dll directly:

$ dumpbin -dependents lib/clang/4.0.0/lib/windows/clang_rt.asan_dynamic-x86_64.dll
...
  Image has the following dependencies:

    KERNEL32.dll
    dbghelp.dll
...

But if dbghelp.dll does, then we have a problem. That's what Etienne is running into.
Comment 5 dmajor 2016-11-07 10:21:59 PST
Ah, right. dbghelp depends on api-ms-win-crt-runtime-l1-1-0, which redirects to ucrtbase.

With /delayload:dbghelp.dll, the error messages went away.
Comment 6 Etienne Bergeron 2016-11-07 10:25:32 PST
I'm facing the exact same bug.

Some allocations are done by ucrt before dynamic hooking (malloc/free interception). Which lead to an error when a free of an unknown object is done.

This is a fix:
  https://reviews.llvm.org/D25946
Comment 7 Reid Kleckner 2016-11-09 16:03:16 PST
Can you guys apply https://reviews.llvm.org/D26473 and test if that fixes your issues?

I wonder if we need to worry the static ASan runtime, too. If we do, then I think we should use LoadLibrary so that users don't need to change their build to delay load dbghelp. Either that or maybe '#pragma comment(linker)' can solve it.
Comment 8 Reid Kleckner 2016-11-09 16:48:04 PST
(In reply to comment #7)
> I wonder if we need to worry the static ASan runtime, too. If we do, then I
> think we should use LoadLibrary so that users don't need to change their
> build to delay load dbghelp. Either that or maybe '#pragma comment(linker)'
> can solve it.

Answering my own question, the test I added failed with the static CRT, so the patch is no good as is.
Comment 9 dmajor 2016-11-14 13:13:49 PST
With r286848 (and with my local patch reverted), I'm no longer getting any complaints from free(). Thanks for the fix!
Comment 10 Reid Kleckner 2016-11-14 19:38:06 PST
Great, fixed in r286848.

We also discussed improving the "attempting free on address which was not malloc()-ed" report to indicate that the pointer comes from the system heap, and indicate that the user should try to debug why heap interception didn't work.
Comment 11 Etienne Bergeron 2016-11-15 09:59:18 PST
It's fixing the first occurrence of the bug.
But, when building chrome, there is other cases.

I'm gonna dig to see which dependency is present.

C:\src\chrome\src>ninja -C out\Asan64 chrome
ninja: Entering directory `out\Asan64'
[1/1] Regenerating ninja files
[16249/27244] ACTION //v8:run_mkpeephole(//build/toolchain/win:clang_x64)
FAILED: gen/v8/bytecode-peephole-table.cc
c:/src/depot_tools/python276_bin/python.exe ../../v8/tools/run.py ./mkpeephole gen/v8/bytecode-peephole-table.cc
=================================================================
==700==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x02bfa8ccf640 in thread T0
    #0 0x7ff69892cfd4 in free c:\src\llvm\src\projects\compiler-rt\lib\asan\asan_malloc_win.cc:45
    #1 0x7ffc665db7fb in qsort+0x46b (C:\Windows\System32\ucrtbase.dll+0x18000b7fb)
    #2 0x7ffc69167ec7 in RtlProcessFlsData+0x117 (C:\Windows\SYSTEM32\ntdll.dll+0x180007ec7)
    #3 0x7ffc69167fb5 in LdrShutdownProcess+0x95 (C:\Windows\SYSTEM32\ntdll.dll+0x180007fb5)
    #4 0x7ffc69167d93 in RtlExitUserProcess+0xb3 (C:\Windows\SYSTEM32\ntdll.dll+0x180007d93)
    #5 0x7ffc66d8ce69 in ExitProcess+0x9 (C:\Windows\System32\KERNEL32.DLL+0x18001ce69)
    #6 0x7ff69899aa07 in exit_or_terminate_process d:\th\minkernel\crts\ucrt\src\appcrt\startup\exit.cpp:129
    #7 0x7ff69899a9a3 in common_exit d:\th\minkernel\crts\ucrt\src\appcrt\startup\exit.cpp:269
    #8 0x7ff698951a36 in __scrt_common_main_seh f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:260
    #9 0x7ffc66d78363 in BaseThreadInitThunk+0x13 (C:\Windows\System32\KERNEL32.DLL+0x180008363)
    #10 0x7ffc691c5e90 in RtlUserThreadStart+0x20 (C:\Windows\SYSTEM32\ntdll.dll+0x180065e90)

Address 0x02bfa8ccf640 is a wild pointer.
SUMMARY: AddressSanitizer: bad-free c:\src\llvm\src\projects\compiler-rt\lib\asan\asan_malloc_win.cc:45 in free
==700==ABORTING
[16254/27244] CXX obj/v8/src/inspector/inspector/Debugger.obj
ninja: build stopped: subcommand failed.