Bagikan melalui


The NT DLL Loader: reentrancy - play along at home!

Anyone care to hazard a guess about what happens if you have the following code in your DllMain()?  Ignore the leak and the lack of error checking; focus on the what the loader's behavior has to be...

BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID lpvReserved) {
    switch (fdwReason) {
    case DLL_PROCESS_ATTACH:
        SOME_FUNCTION_PTR_T pfn = (SOME_FUNCTION_PTR_T) GetProcAddress(LoadLibraryW(L"SomeOther.DLL"), "SomeFunction");
        if (pfn != NULL) (*pfn)();
        break;
    }
    return TRUE;
}

The answer is actually relatively straightforward (the tricky bit is what is GetProcAddress()'s implied contract).  I'll do exposition tomorrow.  For extra credit, consider what the effect of the leak and lack of error checking is on the loader's internal data tables...

Comments

  • Anonymous
    June 21, 2005
    My guess would be that the loader deduces a list of dependencies to load for "SomeOther.DLL" which aren't already imported in the process and aren't already scheduled to be loaded in the loaders list.

    Interestingly if the loader encounters an import in "SomeOther.DLL" that is already in the list to be loaded but has yet to be visited by the loader you could have all sorts of fun 'n' games when calling (*pfn)() (or even before if "SomeOther.DLL"'s initialization section assumes it to be present).

    Am I right in thinking that there will be no deadlock induced by the attempted reacquisition of the loader lock? Simply because it is the same thread acquiring the critical section. (That’s not to say that a deadlock would not happen by some shenanigans in the initialization of "SomeOther.DLL" or one of its dependents)

    Presumably failing to free the library means "SomeOther.DLL" and all it's dependents will never be unloaded from the process until process termination as the loader will always maintain the references.

    I hope I’m not way off the mark :(

  • Anonymous
    June 22, 2005
    The comment has been removed

  • Anonymous
    June 22, 2005
    You're very close. Imagine it worked the way you describe and someone wrote the code above. What bug would they file and how would the loader developer in the early 80s address it? Remember that at that time the NT/win32 community was small and well contained and so people felt that they could always trust their clients.

    Hint: in the normal case, DLL_PROCESS_ATTACH would be issued to SomeOther.DLL. But can you just call it and no other initializers?

  • Anonymous
    June 22, 2005
    The comment has been removed

  • Anonymous
    June 22, 2005
    The comment has been removed

  • Anonymous
    June 22, 2005
    The comment has been removed

  • Anonymous
    June 22, 2005
    Norman, there is no unicode version of GetProcAddress.

  • Anonymous
    June 23, 2005
    Right - the PE export/import tables are all byte oriented strings. It wouldn't even be correct to say that they're MBCS since there's no code page anywhere and it's also incorrect to say that they're CP_ACP since CP_ACP varies user to user and obviously the DLL does not.

    Exports pretty much have to be 7-bit clean. There have been discussions about saying that they're actually utf-8 encoded Unicode/UCS but this isn't compatible with what the existing tool sets do and you have to imagine that there are people dependent on the current implementation.

  • Anonymous
    June 23, 2005
    Thursday, June 23, 2005 4:49 AM by Jeroen Frijters
    > Norman, there is no unicode version of
    > GetProcAddress.

    Ouch. When an API takes a string as a parameter, I think it would be necessary to look it up to see if there are two versions. Oh boy was I wrong. Sorry.

    Thursday, June 23, 2005 1:43 PM by mgrier
    > Exports pretty much have to be 7-bit clean.

    Yup. No other ___W functions take UTF8 format. Furthermore, since the calling thread's ANSI code page can't be assumed to match the ANSI code page that was used on the development machine where the DLL was compiled, we can't convert it to UTF8 for the same reason we can't convert it to UTF16.

    Now wondering why the filename of the DLL doesn't have to be 7-bit clean...

  • Anonymous
    June 23, 2005
    The comment has been removed

  • Anonymous
    June 09, 2009
    PingBack from http://cellulitecreamsite.info/story.php?id=6659

  • Anonymous
    June 16, 2009
    PingBack from http://workfromhomecareer.info/story.php?id=15909