Bug 112592

Summary: prelinking causes mmap() to SEGV in some cases
Product: [Fedora] Fedora Reporter: Kars de Jong <jongk>
Component: prelinkAssignee: Jakub Jelinek <jakub>
Status: CLOSED NOTABUG QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: 1   
Target Milestone: ---   
Target Release: ---   
Hardware: i386   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2003-12-24 00:14:18 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
Example test program none

Description Kars de Jong 2003-12-23 21:36:51 UTC
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1)
Gecko/20031114

Description of problem:
I have upgraded 3 systems previously running Red Hat 9 to Fedora Core
1. I also installed prelink on all of these systems. Today I noticed
that one of my own applications no longer works: it gets a
segmentation violation. I tried running it on the other systems, and
to my surprise it worked fine on one system while it also crashed on
another.

The crash appears to happen inside the C library part of mmap(). When
I use strace I see mmap2() being called and returning successfully,
but when using ltrace the mmap() function hasn't returned yet.

When linking my program statically it worked fine however...
Also, when I disabled prelinking (after I ran /etc/cron.daily/prelink
by hand) it worked fine too. Please note that the program itself
wasn't prelinked yet.

I made a small program to demonstrate the effect.


Version-Release number of selected component (if applicable):
prelink-0.3.0-13

How reproducible:
Sometimes

Steps to Reproduce:
1. Make sure prelinking is enabled
2. Compile mmap_bug.c with "gcc -Wall -O -g -o mmap_bug mmap_bug.c"
2. Run it with "./mmap_bug"
3. SEGV
4. Repeat with ltrace or strace or gdb    

Actual Results:  The program crashes on some systems.


Expected Results:  It should have worked just fine (no output expected).


Additional info:

Comment 1 Kars de Jong 2003-12-23 21:37:58 UTC
Created attachment 96684 [details]
Example test program

Comment 2 Kars de Jong 2003-12-23 21:54:59 UTC
Hmm, it looks like I spoke too soon...
It still crashes sometimes, even with prelinking disabled.

After some more investigation, it looks like the Exec-shield
functionality has something to do with it too. On my system with
Exec-shield enabled and prelink disabled, it still crashes. I
understand why too now, because the fixed memory mapping of 4 MB at
address 0 my program makes sometimes overlaps with the place where the
C library is mapped. Using setarch fixes this issue, and also
disabling Exec-shield globally. However, this doesn't work for a
prelinked library.

I guess I just can't use prelinking in this case, unless I can somehow
make it exclude certain memory ranges... (I *need* the memory mapping
at address 0 since this is some kind of emulator).


Comment 3 Jakub Jelinek 2003-12-24 00:14:18 UTC
Exec-shield places libraries below the binary (starting from
1MB+4KB up to the beginning of the binary).
If your program needs to use MAP_FIXED on a region not given by the kernel to you
(e.g. MAP_FIXED on previously returned address from mmap without MAP_FIXED
if the region is smaller or equal is always ok), then you need to tell the system
about it.
The best way is to create a p_flags 0 PT_LOAD segment with p_filesz 0
and p_memsz equal to the size of the region you want to reserve,
p_vaddr equal to the start address.
Then it will work even with exec-shield, prelinking etc.
ATM it is not exactly trivial to create such PT_LOAD segments, it needs
quite many changes to the linker script (see PHDRS linker script command),
but it is on my TODO list to simplify this.

Alternatively, you need to disable exec-shield for that particular
program.  With rawhide glibc and maybe already rawhide kernel (am not sure
whether the patch is in there already) if you build your program as PIE
and disable exec-shield for it, it should load even prelinked libraries
high.

Or, if you don't want exec-shield system-wide, you can add --no-exec-shield
option to /etc/sysconfig/prelink and force reprelinking.