|
From: John R. <jr...@Bi...> - 2006-12-31 22:50:19
|
Julian Seward wrote: > I've been testing the 3.2 branch on OpenSUSE 10.2 (kernel 2.6.18.2, glibc-2.5) > and mostly it works pretty well. However, it can't run bash: ... > sys_mmap ( 0xFFFDE000, 69636, 5, 2050, 3, 0 ) --> [pre-fail] Failure(0xC) > sys_mmap ( 0xFFFD9000, 90236, 5, 2050, 3, 0 ) --> [pre-fail] Failure(0xC) > sys_mmap ( 0xFFFA1000, 319664, 5, 2050, 3, 0 ) --> [pre-fail] Failure(0xC) > > This strikes me as strange because the addresses (0xFFFDE000 etc) are almost > at the end of 4G. It's also strange because other programs, including large > ones, run just fine, and these .so's are mapped quite low, as is normal. It's also strange because the file offset (6th argument) is 0 from the same fd 3 (5th argument) but with three different sizes (2nd argument). Is this three successive attempts at a single mapping, or serial execution of a parallel mapping? > > Is it legitimate for ld.so to attempt to map anything to the 0xFFFDxxxx > areas? Without MAP_FIXED in the 4th argument, then a non-zero 1st argument is just a preference which the kernel may choose to ignore, and should ignore if outside the apparent 2G user space. ld-linux sets such a preference for a pre-linked .so. This can be done by mmap(phdr[0].p_vaddr, ... which "just happens" to be what ET_EXEC also requires. Doing a plain 'cat /proc/self/maps' shows that the stack is placed > just below the 2G boundary and there is nothing above, which makes me > think this kernel is running in a 2G+2G configuration. ... I have encountered similar symptoms on x86 without valgrind and with earlier versions of kernel and glibc and my code. The sys_mmap ( 0xFFFDE000, 69636, 5, 2050,,) with a first argument that is close to 4G suggests a mixup with respect to pre-linking and/or -fPIE (position-independent executable) and/or policy to randomize address space. The address was formed by subtracting a size from 0. 2050==0x802 ==> (MAP_EXEC | MAP_DENYWRITE) which is the usual protection for shared .text, and does not include MAP_FIXED (0x10). This also is suspicious, because without MAP_FIXED the kernel gives no guarantee of relative position among the 3 PT_LOAD from the same file, which /bin/ld [or the creator of that file] probably expected. And if MAP_FIXED _is_ present, then there should have been a prior "reservation" mmap() of size roundup(69636) + roundup(90236) + roundup(319664) in order for ld-linux to preserve relative position. Run under strace. Note which file corresponds to fd 3, and run "readelf --segments" on that file. There should be 3 PT_LOAD with sizes that match the second argument to mmap(), unless the 6th argument being 0 is telling us that these were successive attempts at a single mapping, instead of serialized implementation of parallel mapping. If the .p_vaddr of the lowest-addressed PT_LOAD is not 0, then pre-linking definitely is involved. Un-prelink (and/or un-PIE, and/or un-set random assignment policy) and try again. If .p_vaddr is 0, then consult the code to ld-linux. Also check the recent history of fs/binfmt_elf.c and related vma code in linux kernel. -- |