X-Recipient: archive-cygwin AT delorie DOT com X-Spam-Check-By: sourceware.org Date: Fri, 5 Jun 2009 23:30:12 +0200 From: Corinna Vinschen To: cygwin AT cygwin DOT com Subject: Re: ASLR sometimes stops working on Vista with 1.7? [was: Re: Cygwin 1.7 release (was ...)] Message-ID: <20090605213012.GG23519@calimero.vinschen.de> Reply-To: cygwin AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com References: <1244131746 DOT 30024 DOT 1318796263 AT webmail DOT messagingengine DOT com> <4A282063 DOT 9030804 AT users DOT sourceforge DOT net> <4A286B99 DOT 6020702 AT users DOT sourceforge DOT net> <20090605120936 DOT GD23519 AT calimero DOT vinschen DOT de> <4A293237 DOT 2010102 AT cwilson DOT fastmail DOT fm> <20090605163510 DOT GF23519 AT calimero DOT vinschen DOT de> <4A296778 DOT 2080507 AT cwilson DOT fastmail DOT fm> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <4A296778.2080507@cwilson.fastmail.fm> User-Agent: Mutt/1.5.19 (2009-02-20) Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com On Jun 5 14:44, Charles Wilson wrote: > Corinna Vinschen wrote: > > However, if I rebase the DLL to some other spot, like 0x65000000, then > > the DLL is loaded at that address exactly, and everything works fine. I > > still don't think this has anything to do with ASLR. ASLR only > > complicates the picture. AFAICS, there's no guarantee that the address > > computed by ASLR will help forever. It only eases the underlying > > problem by chance if the addresses happen to have a low chance for > > collision. > > One of the side effects of ASLR is to, in effect, perform a custom > rebase for every dynbase-enabled DLL, that is (a) unique to the usage > pattern of your machine workflow since you (booted/logged on), and (b) > includes not just cygwin DLLs but also all normal system DLLs so marked, > and (c) persists for the entirety of the current boot/logon session. > This means very little chance of collision at all, AFIACT, at least not > any that arise from (new)ImageBase+codesize. > > For ASLR, all dynbase DLLs (including cygwin ones) get mapped to the > range 0x50000000 to 0x78000000. If something ends up at 0x900000, either > with +dynbase/ASLR or without, it's not directly related to ASLR... That's what I'm trying to say. ASLR is probably helping in the normal use case. But if the DLL's ALSR memory slot is taken by something else (for instance, a non-ASLR DLL), the new DLL will have to be relocated by the system, same as without ASLR. It might be a helpful technique, but it's far from a one-size-fits-all solution. > > The problem is not the fact that the DLL is rebased at all in the > > parent. Even though in my case the address range 0x6ee00000-0x6ee08000 > > isn't taken by another DLL, it could be taken by memory dynamically > > allocated by one of the formerly loaded DLLs. > > Really? This would have to be by virtue of some call OTHER than to > cygwin's malloc, right? In theory, yes, but not necessarily. malloc does not use the heap exclusively. Big chunks of memory (>128K) are allocated using mmap() with the MAP_PRIVATE|MAP_ANONYMOUS flags. Private anonymous maps are implemented using VirtualAlloc with the MEM_TOP_DOWN flag. > Because I thought cygwin maintained a single > process heap way down low in memory...it's hardly likely for that heap > to clash with 0x50000000...0x78000000 (or, for the original rebase, > non-ASLR scenario, 0x68000000...downwards), for small allocations like > this (e.g. where your solution of adding a single page to the > DefaultOffset size as a buffer helps). It's definitely not a collision with the heap which results in rebasing the DLL in the parent. > If it's a cygwin-linked DLL doing this (e.g. Dumper.dll) maybe it's a > bug in that DLL, using the wrong mechanism to allocate memory (e.g. a > direct call to VirtualAlloc or to (deprecated) GlobalAlloc or LocalAlloc > functions?) ...Hmm, perl itself (incl. Dumper.dll) doesn't seem to. > > > The real shit starts with the fact that W7 (and Vista, too, apparently) > > rebases the DLL to an address which is so very low in the address space > > of the application. > > But why did it do this at all? In the normal "rebase" scenario (and > assuming no dynamically allocated memory sucking up 0x68000000-level > space), sure -- I could see some other system DLL interfering with where > rebase wanted to put, e.g. Cwd.dll. That's not the case. There's no DLL loaded into the address in question. At least not if I ask WinDbg. Either the memory is taken by something else (I don't know what it is), or the OS decides that DLLs shouldn't spoon with each other (think of the children) and rebases the DLL for decency. [...time passes...] WinDbg confirms that the memory is taken by something else. Dumper.dll is located in the area 0x6ede0000 - 0x6eded000. The next three pages from 0x6eded000 - 0x6edf000 are free. The following memory region from 0x6edf0000 - 0x6ee01000 (68K, huh?) consists of commited R/W pages allocated in a single allocation call. Examining the content of the commited memory region starting at 0x6edf0000 shows something surprising. After a couple of arbitrary bytes, there's a 4 byte value 68, followed by the WCHAR string \\?\C:\cygwin\lib\perl5\5.10\i686-cygwin\auto\Data\Dumper\Dumper.dll which is exactly 68 wide characters long. The entire reminder of the memory region is set to 0. The fact that the path has a leading \\?\ points to something in the Cygwin DLL allocating that memory, perhaps in dlopen. But why at this memory address?!? > > Some perl DLL (Dumper.dll?) allocates additional memory and that's right > > after it's own image. That's where Cwd.dll is based to. Cwd.dll gets > > rebased and ... poof. > > Right then. So...why? Seems odd that the dynamic allocation is occuring > "up high" and not down in user_heap. Absolutely. Especially after finding what's in that memeory region... > >> Could it be possible that cygwin's dlopen (or fork) implementation is > > Not that I can see. The memory for the data storing the loaded DLLs is > > loaded from the parent memory into a stack slot. There's no other > > memory allocation going on. Well, except when LoadLibrary already > > failed. > > Ack. Good. Cygwin's fork/exec code is much much scarier to me than > memory allocation... Not good. I'm puzzled where this allocated 68K region is exactly coming from, but it really looks like something which occurs in or near dlopen. I'm going to debug this further tomorrow. I guess that goes without saying, but I'd be glad for any help. Corinna -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Project Co-Leader cygwin AT cygwin DOT com Red Hat -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/