This is the mail archive of the cygwin-patches mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Improvements to fork handling (2/5)


On 24/05/2011 9:05 AM, Corinna Vinschen wrote:
On May 24 07:27, Ryan Johnson wrote:
On 23/05/2011 3:31 AM, Corinna Vinschen wrote:
On May 22 14:42, Ryan Johnson wrote:
In theory, this should completely eliminate the case where us
loading one DLL pulls in dependencies automatically (= uncontrolled
and at Windows' whim). The problem would manifest as a DLL which
"loads" in the same wrong place repeatedly when given the choice,
and for which we would be unable to VirtualAlloc the offending spot
(because the dll in question has non-zero refcount even after we
unload it, due to the dll(s) that depend on it.
There might be a way around this.  It seems to be possible to tweak
the module list the PEB points to so that you can unload a library
even though it has dependencies.  Then you can block the unwanted
space and call LoadLibrary again.  See (*) for a discussion how
you can unload the exe itself to reload another one.  Maybe that's
something we can look into as well.  ObNote:  Of course, if we
could influnce the address at which a DLL gets loaded right from the
start, it would be the preferrable solution.


Corinna


(*) http://www.blizzhackers.cc/viewtopic.php?p=4332690
After poking around at (*) a bit, it looks like NtMapViewOfSection
does more than I would have expected wrt dll loading. However, when
I tried to fire up a toy program to test it, NtOpenSection always
returns C0000024, regardless of whether I pass OBJ_KERNEL_HANDLE to
it.

Does anybody have experience with those two functions?
The Cygwin source code, for instance, is using this function, see
fhandler_mem.cc.

C0000024 is STATUS_OBJECT_TYPE_MISMATCH.  I didn't see the error before,
but I have a vague idea why you get it.  Are you by any chance trying to
call NtOpenSection with the OBJECT_ATTRIBUTES set to the file?  If so,
that's wrong.  The OBJECT_ATTRIBUTES names the attributes of the section,
including its name if it has one.  It does not specify the file you're
trying to map.  What you're looking for is NtCreateSection.  It has an
extra parameter to specify the handle to an open file.
Bingo. That was indeed it.

So, playing with NtMapViewOfSection (code below) shows that it knows how to map a .dll properly (with appropriate permissions for the various sections), and you can force it to map to a given address, but the resulting image is not considered a proper .dll -- it doesn't show up in the dll list and initialization routines don't run (I haven't checked dependency loading yet). Most likely, this is roughly equivalent to LoadLibraryEx+DONT_RESOLVE_DLL_REFERENCES.

Another issue arises if the file is mapped to somewhere other than its preferred image base. In this case the mapping succeeds but returns STATUS_IMAGE_NOT_AT_BASE, in which case LdrRelocateImage and its friends need to be called.

An additional difficulty: trying to CreateFile a well-known dll like psapi returns STATUS_WAIT_3, so file locking seems to be an issue. This happens even if I pass all possible sharing flags (0x7).

Overall, it looks like going this route would strongly resemble the custom loader option. There Be Dragons...

Meanwhile, the forced unload of the .exe is really tantalizing, but it sounds there's a lot of messiness trying to clean up the mess and load the new image. Granted, this would be simpler since we're trying to reload the same image (after loading its dependent dlls properly), and we already know what dlls need to be loaded by looking at the parent process. However, we'd have to do this without unloading cygwin1.dll (maybe calling LoadLibrary on it would bump the refcount and protect it?).

On the other hand, if we could get that forced unload to work reliably, we'd almost have a true exec() on our hands and could use that to implement fork: run a stub process, load the dlls we know we'll need, then replace the stub with the actual image we want to run and clean up the mess we left in the PEB... that would let us control nearly all dlls, even windows ones.

Ryan


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]