This is the mail archive of the cygwin 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: Two probable basing issues causing fork failures: (1) cygreadline7.dll has ASLR enabled, (2) default base address conflicts with ASLR-relocated/system DLLs

> -----Original Message-----
> Sent: Monday, April 23, 2012 14:51
> Subject: Re: Two probable basing issues causing fork failures: (1)
> cygreadline7.dll has ASLR enabled, (2) default base address conflicts with
> ASLR-relocated/system DLLs
> Yes, it is a problem in the first place if DLLs have the dynamicbase flag set,
> because, obviously, it undermines what rebaseall is doing.
> It's not a problem if the new address it gets rebased to doesn't collide with
> any other used DLL since ASLR on Windows only shuffles ASLR-enabled DLL
> addresses when a DLL is loaded by an application for the first time.
> Afterwards, it will use the new address for that DLL until reboot.
> So, yes, we should make sure that the ASLR flag is not used for Cygwin DLLs.

Well, that's what I figured...  Thanks for investigating!

I also thought that an ASLR-relocated DLL would keep the same random base address until reboot.  But on the Cygwin 1.7.9 system I mentioned in the original e-mail, I would have sworn that ASLR was not consistently basing cygreadline7.dll in the same place even in the same user session, even when multiple instances of Cygwin were running.  I wish I took screenshots or took better documentation or something though.  It wasn't just a random error - it was failing every single time - I couldn't launch any process at all from bash.

There is certainly no guarantee that ASLR DLLs will never be relocated after first load and until reboot.  A quick demonstration:

// compile with DYNAMICBASE:NO and NXCOMPAT:NO
#include <windows.h>
#include <iostream>
#include <iomanip>
int main() {
	HMODULE hm = LoadLibrary(_T("RandomASLRDLL.dll"));
	std::cout << std::hex << reinterpret_cast<size_t>(hm) << std::endl;
	char c[50];
	std::cin.getline(c, 50);
	return 0;

Every execution seemed to alternate between two different base addresses.  However, running multiple instances at a time seemed to cause them to share the same base address.  Maybe with more work I could get the loader to violate that assumption as well...

Or maybe I'm remembering things wrong from what I saw.  (very possible!)  I'll be keeping an eye out.

> As for the address space, we should stick to using the addresses below
> 0x70000000, top-down.  The reason is that we also need room for the
> application heap.  On 32 bit systems the heap will be placed at 0x20000000
> and in case it's too small it will be extended up to the start address of the
> Cygwin DLL (minus 3 * 64K).

This explains why the base address for Cygwin1.dll was at 0x61000000 while rebaseall has DefaultBaseAddress=0x70000000.... it's top-down... makes sense - somehow I missed that detail.

But on systems with ASLR, I noticed multiple ASLR system DLLs in this address range.  Even on clean Windows XP SP3 installations there was a system DLL in the 0x60000000 - 0x70000000 range.  Isn't it just by luck that the DLLs didn't conflict and cause one to be relocated?  (Or does Cygwin rebasing have some more smarts I am overlooking, like working around system DLLs that are already loaded?  Although, that wouldn't help with ASLR DLLs... it still sounds risky.  And Windows Update will potentially change the DLLs, too.)

Certainly heap space is a compromise - I thought of that - but I would guess most Cygwin users don't need it.  At least, this one doesnât!

For users who don't need to maximize heap space at the possible expense of fork() reliability, is it safe to say that a lower top-end rebase address would be a lot safer?  For example, running this after installing Cygwin for the first time:

rebaseall -b 0x60000000

(or maybe even 0x50000000 if you really don't need the heap space?)

Or are there other factors I am overlooking?


Problem reports:
Unsubscribe info:

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