Udostępnij za pośrednictwem


The NT DLL Loader: DLL_PROCESS_ATTACH reentrancy - wrap up

Hopefully the culmination of these cautionary tales is clear: you're walking a very fine line when you attempt to reenter the loader from within a loader callout.  You're (more!) subject to ordering and cycle issues, you can force initialization to proceed on to your dependencies even if you're not ready for them to call in to you and failure to propagate failures from the loader is fatal.

Spot the bug that corrupted/crashed your process:

if (GetFileAttributesW(pszSomePath) != 0xffffffff) {
    // process the file
}

Where was it?  Oh, right, GetFileAttributes might actually be a linker delayload!  So it's actually an invisible wrapper around calling into the loader!  And I didn't remember to propagate loader errors!  Hmm... how do I even know that the error code was a loader error?

I consider this class of bug to be unstomachable.  Looking at the souce it seems obvious that there's a bug there.  At least you should be looking for ERROR_FILE_NOT_FOUND / ERROR_PATH_NOT_FOUND, not just treating all errors as file not found.  But who says that those errors are not propagated out of the delayload stubs in the case that the load failed?  (This particular case is arguably obtuse; GetFileAttributesW is in kernel32 which will already have been loaded and initiailzed but the point is still valid.)

I'll provide an in-depth wrap up of all the general cautions and what to do about them but this series should make you feel very very nervous indeed if you have code in your DLL_PROCESS_ATTACH that's doing much more than calling InitializeCriticalSection().

Comments