Bug 25749 - Non-const relocation against SHN_ABS symbol in PIE or shared library should be disallowed
Summary: Non-const relocation against SHN_ABS symbol in PIE or shared library should b...
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.35
: P2 normal
Target Milestone: 2.35
Assignee: Not yet assigned to anyone
URL: https://sourceware.org/pipermail/binu...
Keywords:
Depends on:
Blocks:
 
Reported: 2020-03-30 12:42 UTC by H.J. Lu
Modified: 2020-04-02 11:46 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description H.J. Lu 2020-03-30 12:42:16 UTC
[hjl@gnu-cfl-2 pr94391]$ cat a.c 
extern unsigned long _binary_a_c_size __attribute__ ((visibility ("hidden")));
unsigned long
foo (void)
{
  return (unsigned long) &_binary_a_c_size;
}
[hjl@gnu-cfl-2 pr94391]$ make
gcc -B./ -g -fpic   -c -o a.o a.c
objcopy -B i386:x86-64 -I binary -O elf64-x86-64 a.c x.o
./ld -shared -o liba.so a.o x.o
[hjl@gnu-cfl-2 pr94391]$ 

There is no way to correctly resolve PC relocation against SHN_ABS symbol
in PIE or shared library without introducing new special PC relocation.

[hjl@gnu-cfl-2 pr94391]$ ld.lld -shared -o liba.so a.o x.o
ld.lld: error: relocation R_X86_64_PC32 cannot refer to absolute symbol: _binary_a_c_size
>>> defined in x.o
>>> referenced by a.c:5
>>>               a.o:(foo)
[hjl@gnu-cfl-2 pr94391]$
Comment 1 Fangrui Song 2020-03-30 15:38:23 UTC
Thanks for opening this issue.

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94391#c6

It is incorrect to reference a non-preemptible SHN_ABS symbol with a PC relative relocation in a PIC (-shared or -pie) link. This is non-representable due to ASLR (load base not fixed at link time)

There are several ways that the symbol will be considered non-preemptible:

* -pie
* -Bsymbolic
* STV_HIDDEN/STV_INTERNAL/STV_PROTECTED
* --dynamic-list exists but does not list the symbol
* VER_NDX_LOCAL
Comment 2 H.J. Lu 2020-03-30 18:41:51 UTC
Since the value of SHN_ABS symbol is a constant, only S - A relocations
should be allowed in PIE and shared library, which means only BFD_RELOC_8,
BFD_RELOC_16, BFD_RELOC_32, and BFD_RELOC_64 are allowed for SHN_ABS symbol
in PIE and shared library.
Comment 3 H.J. Lu 2020-03-31 04:45:55 UTC
A patch is posted at

https://sourceware.org/pipermail/binutils/2020-March/110448.html
Comment 4 Sourceware Commits 2020-04-01 21:32:52 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=382aae06322799a25ea52fe61b243cbca4db8d66

commit 382aae06322799a25ea52fe61b243cbca4db8d66
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Wed Apr 1 14:31:47 2020 -0700

    x86: Only allow S + A relocations against absolute symbol
    
    Since value of non-preemptible absolute symbol (SHN_ABS) won't change,
    only relocations, which can be resolved as absolute value + addend, and
    GOTPCREL relocations, where absolute value + addend is stored in the GOT
    slot, against non-preemptible absolute symbol are allowed in PIE and
    shared library.
    
    Also convert load relocation to R_386_32, R_X86_64_32S or R_X86_64_32 for
    relocation against non-preemptible absolute symbol.  Don't convert to
    R_X86_64_32S nor R_X86_64_32 for non-preemptible absolute symbol if they
    overflow.
    
    bfd/
    
            PR ld/25749
            PR ld/25754
            * elf32-i386.c (elf_i386_convert_load_reloc): Convert load
            relocation to R_386_32 for relocation against non-preemptible
            absolute symbol.
            (elf_i386_check_relocs): Call _bfd_elf_x86_valid_reloc_p.  Don't
            allocate dynamic relocation for non-preemptible absolute symbol.
            (elf_i386_relocate_section): Pass sec to
            GENERATE_DYNAMIC_RELOCATION_P.
            * elf64-x86-64.c (R_X86_64_converted_reloc_bit): Moved.
            (elf_x86_64_convert_load_reloc): Covert load relocation to
            R_X86_64_32S or R_X86_64_32 for relocation against non-preemptible
            absolute symbol.  Don't convert to R_X86_64_32S nor R_X86_64_32
            for non-preemptible absolute symbol if they overflow.
            (elf_x86_64_check_relocs): Call _bfd_elf_x86_valid_reloc_p.  Set
            tls_type for GOT slot to GOT_ABS for non-preemptible absolute
            symbol.  Don't allocate dynamic relocation for non-preemptible
            absolute symbol.
            (elf_x86_64_relocate_section): Don't generate relative relocation
            for GOTPCREL relocations aganst local absolute symbol.  Pass sec
            to GENERATE_DYNAMIC_RELOCATION_P.
            * elfxx-x86.c (elf_x86_allocate_dynrelocs): No dynamic relocation
            against non-preemptible absolute symbol.
            (_bfd_elf_x86_valid_reloc_p): New function.
            (_bfd_x86_elf_size_dynamic_sections): No dynamic relocation for
            GOT_ABS GOT slot.
            * elfxx-x86.h (GENERATE_DYNAMIC_RELOCATION_P): Add an SEC
            argument.  Don't generate dynamic relocation against
            non-preemptible absolute symbol.
            (ABS_SYMBOL_P): New.
            (GENERATE_RELATIVE_RELOC_P): Don't generate relative relocation
            against non-preemptible absolute symbol.
            (GOT_ABS): New.
            (R_X86_64_converted_reloc_bit): New.  Moved from elf64-x86-64.c.
            (_bfd_elf_x86_valid_reloc_p): New.
    
    ld/
    
            PR ld/25749
            PR ld/25754
            * testsuite/ld-elf/linux-x86.exp: Run ld/25749 tests.
            * testsuite/ld-elf/pr25749-1.c: New file.
            * testsuite/ld-elf/pr25749-1a.c: Likewise.
            * testsuite/ld-elf/pr25749-1b.c: Likewise.
            * testsuite/ld-elf/pr25749-1b.err: Likewise.
            * testsuite/ld-elf/pr25749-1c.c: Likewise.
            * testsuite/ld-elf/pr25749-1d.c: Likewise.
            * testsuite/ld-elf/pr25749-2.c: Likewise.
            * testsuite/ld-elf/pr25749-2a.s: Likewise.
            * testsuite/ld-elf/pr25749-2b.s: Likewise.
            * testsuite/ld-elf/pr25749.rd: Likewise.
            * testsuite/ld-elf/pr25754-1a.c: Likewise.
            * testsuite/ld-elf/pr25754-1b.s: Likewise.
            * testsuite/ld-elf/pr25754-2a.c: Likewise.
            * testsuite/ld-elf/pr25754-2b.err: Likewise.
            * testsuite/ld-elf/pr25754-2b.s: Likewise.
            * testsuite/ld-elf/pr25754-3a.c: Likewise.
            * testsuite/ld-elf/pr25754-3b.s: Likewise.
            * testsuite/ld-elf/pr25754-4a.c: Likewise.
            * testsuite/ld-elf/pr25754-4b.s: Likewise.
            * testsuite/ld-elf/pr25754-4c.s: Likewise.
            * testsuite/ld-elf/pr25754-5a.c: Likewise.
            * testsuite/ld-elf/pr25754-5b.s: Likewise.
            * testsuite/ld-elf/pr25754-5c.s: Likewise.
            * testsuite/ld-elf/pr25754-6a.c: Likewise.
            * testsuite/ld-elf/pr25754-6b.s: Likewise.
            * testsuite/ld-x86-64/pr19609-6a.d: Don't expect linker error.
Comment 5 H.J. Lu 2020-04-01 21:33:36 UTC
Fixed for 2.35.
Comment 6 Sourceware Commits 2020-04-02 11:46:11 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=516231b7c7278e4e5a726cff1f798beb4bbce73c

commit 516231b7c7278e4e5a726cff1f798beb4bbce73c
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Apr 2 04:44:01 2020 -0700

    linux-x86.exp: Compile with -I../bfd
    
    Compile with -I../bfd to include <bfd_stdint.h> in PR ld/25749 tests.
    
            * testsuite/ld-elf/linux-x86.exp (check_pr25749a): Compile with
            -I../bfd.
            (check_pr25749b): Likewise.