bug-binutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when lo


From: mintsuki at protonmail dot com
Subject: [Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
Date: Tue, 28 May 2024 16:25:53 +0000

https://sourceware.org/bugzilla/show_bug.cgi?id=31795

--- Comment #61 from mintsuki <mintsuki at protonmail dot com> ---
(In reply to mintsuki from comment #59)
> (In reply to Adhemerval Zanella from comment #58)
> > (In reply to mintsuki from comment #41)
> > > (In reply to Adhemerval Zanella from comment #39)
> > > > (In reply to Fangrui Song from comment #37)
> > > > > I agree with mintsuki . The "-pie -Ttext-segment=non-zero => ET_EXEC" 
> > > > > hack
> > > > > should not be needed.
> > > > > 
> > > > > From 
> > > > > https://sourceware.org/pipermail/binutils/2013-December/083381.html
> > > > > 
> > > > > > Linker sets e_type in ELF header to ET_DYN for -pie 
> > > > > > -Ttext-segment=0xXXX.
> > > > > > When I added -Ttext-segment=0xXXX, one goal was to load
> > > > > > small model executable above 4GB on Linux/x86-64, which
> > > > > > was done with -pie -Ttext-segment=0xXXX.  But -pie sets
> > > > > > e_type in ELF header to ET_DYN and kernel may ignore
> > > > > > p_vaddr in ELF header to load ET_DYN binary at a random
> > > > > > address.  This patch changes ld to set e_type in ELF header
> > > > > > to ET_EXEC if the first PT_LOAD segment has non-zero
> > > > > > p_vaddr.  If this is unacceptable as generic ELF change,
> > > > > > I can make it specific to x86.
> > > > > 
> > > > > Was the intention for the following command to load the text segment 
> > > > > at an
> > > > > address >= 0x600000000000 ?
> > > > > 
> > > > > ```
> > > > > % cat a.c
> > > > > #include <stdio.h>
> > > > > int main() { printf("%p\n", main); }
> > > > > % gcc -pie -Wl,-no-pie a.c -fuse-ld=bfd
> > > > > -Wl,--no-relax,-Ttext-segment=0x600000000000 -o a
> > > > > % ./a
> > > > > 0x600000001139
> > > > > % ./a
> > > > > 0x600000001139  # no ASLR
> > > > > ```
> > > > > 
> > > > > Changing ET_DYN to ET_EXEC fulfills the address requirement but 
> > > > > disables
> > > > > ASLR.
> > > > > Is it intentional?
> > > > 
> > > > That's my understanding of reading the -Ttext-segment documentation.  
> > > > The
> > > > question is whether we relax the semantic to have it as a minimum 
> > > > address or
> > > > define it as the expected address (thus disabling ASLR as a 
> > > > consequence). 
> > > 
> > > My understanding is that the PT_LOAD PHDR addresses could be slid, as long
> > > as they are slid above the specified address. The fact that the first
> > > PT_LOAD PHDR is 0 or not should be irrelevant. It makes no sense for it to
> > > be relevant, let alone for it to dictate the ELF type to be ET_EXEC.
> > > 
> > > This is how Limine behaves, and how I interpret the ELF format.
> > 
> > Unfortunately, this is not what binutils documentation states ("When
> > creating an ELF executable, it will set the address of the first byte of the
> > text segment") nor how Linux handles it (where ET_DYN does not enforce
> > e_entry).
> > 
> > And it seems to be a Linux-specific issue, since on FreeBSD:
> > 
> > $ cc -pie a.c -fuse-ld=lld -Wl,--no-relax,--image-base=0x600000000000
> > -Wl,-z,notext -o a-lld
> > $ readelf -h a-lld
> > ELF Header:
> >   Magic:   7f 45 4c 46 02 01 01 09 00 00 00 00 00 00 00 00
> >   Class:                             ELF64
> >   Data:                              2's complement, little endian
> >   Version:                           1 (current)
> >   OS/ABI:                            FreeBSD
> >   ABI Version:                       0
> >   Type:                              DYN (Shared object file)
> >   Machine:                           Advanced Micro Devices x86-64
> >   Version:                           0x1
> >   Entry point address:               0x6000000016b0
> >   Start of program headers:          64 (bytes into file)
> >   Start of section headers:          12928 (bytes into file)
> >   Flags:                             0
> >   Size of this header:               64 (bytes)
> >   Size of program headers:           56 (bytes)
> >   Number of program headers:         11
> >   Size of section headers:           64 (bytes)
> >   Number of section headers:         39
> >   Section header string table index: 37
> > $ readelf -d a-lld  | grep -w FLAGS_1
> >  0x000000006ffffffb FLAGS_1              PIE
> > $ doas sysctl -w kern.elf64.aslr.pie_enable=1
> > kern.elf64.aslr.pie_enable: 0 -> 1
> > $ ./a-lld
> > 0x6000000019d0
> > $ ./a-lld
> > 0x6000000019d0
> > 
> > So maybe we either enable this iff targeting Linux, or check if kernel is
> > willing to enforce e_entry even for DYN. 
> > 
> > I am not sure if the correct approach is relaxing the
> > '-Ttext-segment/--image-base' to be a minimum address.  For this, I would
> > add another linker option.
> 
> I am not sure what you mean with "willing to enforce e_entry".
> 
> In any case, how about checking what the generated ELF file's OS/ABI is and
> only doing the DYN->EXEC hack if it happens to be GNU/Linux?

Actually I don't think that may be possible, at least not by checking the
OS/ABI field alone, given on my Linux host it seems to be a generic UNIX -
System V value...

-- 
You are receiving this mail because:
You are on the CC list for the bug.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]