[PATCH RFC] fork: reduce chances for "address space is already occupied" errors

Michael Haubenwallner michael.haubenwallner@ssi-schaefer.com
Thu Mar 28 09:17:00 GMT 2019


On 3/28/19 9:34 AM, Michael Haubenwallner wrote:
> On 3/27/19 10:16 AM, Corinna Vinschen wrote:
>> On Mar 27 09:26, Michael Haubenwallner wrote:
>>> On 3/26/19 7:28 PM, Corinna Vinschen wrote:
>>>> On Mar 26 19:25, Corinna Vinschen wrote:
>>>>> On Mar 26 18:10, Michael Haubenwallner wrote:
>>>>>> Hi Corinna,

>>
>>>> Btw., is that 32 or 64 bit?  Both?
>>>
>>> I'm on 64bit only, can't say for 32bit.  And while in theory possible,
>>> I'm not after supporting 32bit Cygwin in Gento Prefix at all...
>>
>> If so, then I'm really curious how many DLLs are affected and why this
>> occurs on 64 bit.
>>
>> As you know, 64 bit has a defined memory layout.  Binutils ld is
>> supposed to base the DLLs to a pseudo-random address in the area between
>> 0x4:00000000 and 0x6:00000000.  This area is occupied by un-rebased DLLs
>> only.  8 Gigs is a *lot* of space for DLLs.
>>
>> That also means that the DLLs should not at all collide with windows
>> objects (typically reserved in the lesser 2 Gigs area), unless they
>> collide with themselves.  At least that's the idea.
>>
>> Can you check what addresses the freshly built DLLs are based on by LD?
>> Is there a chance that the algorithm used in LD is too dumb?
> 
> I've also added system_printf to dll_list::reserve_space() when a dynloaded
> dll was relocated, and each new address was below 0x0:01000000. The attached
> output also contains the preferred address, above 0x4:00000000 each.
> 
>>
>> Or, hmm.  Is there a chance that newer Windows loads dynamically loaded
>> DLLs whereever it likes, ignoring the base address, ASLR-like, even
>> if the DLL is marked as non-ASLR-aware?  But then again, we should have
>> a lot more complaints on the list...
> 
> I've done this test on Windows Server 2012R2, but the problem exists on
> 2016 and 2019 as well (I'm not testing with other Windows versions).
> 
>>>>>>  I'm
>>>>>> coming up with attached patch.
>>>>>>
>>>>>> What do you think about it?
>>>>>
>>>>> I'm not opposed to this patch but I don't quite follow the description.
>>>>> threadinterface->Init only creates three event objects.  From what I can
>>>>> tell, Events are stored in Paged and Nonpaged Pools, so they don't
>>>>> affect the processes VM.  What am I missing?
>>>
>>> Honestly, I'm not completely sure whether this patch really does help:
>>> Beyond the Events, there also is CreateNamedPipe and CreateFile used
>>> in fhandler_pipe::create via sigproc_init, and these causing the address
>>> conflicts with some dll actually is nothing more than a wild guess:
>>> While their returned handles are below the conflicting dll address,
>>> who can tell what these API calls do allocate internally?
>>
>> The handles are not addresses.  If the sigproc_init stuff collides,
>> I only see two chances for that, the process-local read/write buffers
>> of the signal pipe, and the stack of the read_sig thread.
>>
>> If this patch helps your situation, we can pull it in and test it,
>> but I think your situation asks for more debugging along the lines
>> of the DLL rebasing above.
> 
> With this patch collisions seem gone, yet the relocations do happen.

Ehm... collisions still do happen, but less often at least,
so this patch does help in my situation.

As it is not some other dll being loaded at the colliding adress: any
idea how to find out _what_ is allocated there (in the forked child),
to find out whether we can reserve these areas even more early?

What if we adapt the initial dlopen call to disallow relocation into
such low address space?

Beyond that, I'm going to learn about rebase --oblivious, thanks Achim!

/haubi/



More information about the Cygwin-patches mailing list