From: "H.J. Lu" <hjl.tools@gmail.com>
To: binutils@sourceware.org
Subject: [PATCH] x86: Only allow S - A relocations against absolute symbol
Date: Mon, 30 Mar 2020 21:43:50 -0700 [thread overview]
Message-ID: <20200331044350.808132-1-hjl.tools@gmail.com> (raw)
Since value of non-preemptible absolute symbol (SHN_ABS) won't change,
only S - A relocations against non-preemptible absolute symbol are
allowed in PIE and shared library.
bfd/
PR ld/25749
* elf32-i386.c )elf_i386_relocate_section): Call
_bfd_elf_x86_valid_reloc_p. Pass sec to
GENERATE_DYNAMIC_RELOCATION_P.
* elf64-x86-64.c (elf_x86_64_relocate_section): Likewise.
* elfxx-x86.c (_bfd_elf_x86_valid_reloc_p): New function.
* elfxx-x86.h (GENERATE_DYNAMIC_RELOCATION_P): Add an SEC
argument. Don't generate dynamic relocation for relocation
against SHN_ABS symbol.
(_bfd_elf_x86_valid_reloc_p): New.
ld/
PR ld/25749
* 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-2.c: Likewise.
* testsuite/ld-elf/pr25749-2a.s: Likewise.
* testsuite/ld-elf/pr25749-2b.s: Likewise.
---
bfd/elf32-i386.c | 6 +-
bfd/elf64-x86-64.c | 6 +-
bfd/elfxx-x86.c | 53 +++++++++++
bfd/elfxx-x86.h | 8 +-
ld/testsuite/ld-elf/linux-x86.exp | 135 +++++++++++++++++++++++++++++
ld/testsuite/ld-elf/pr25749-1.c | 12 +++
ld/testsuite/ld-elf/pr25749-1a.c | 11 +++
ld/testsuite/ld-elf/pr25749-1b.c | 9 ++
ld/testsuite/ld-elf/pr25749-1b.err | 3 +
ld/testsuite/ld-elf/pr25749-1c.c | 9 ++
ld/testsuite/ld-elf/pr25749-2.c | 12 +++
ld/testsuite/ld-elf/pr25749-2a.s | 6 ++
ld/testsuite/ld-elf/pr25749-2b.s | 7 ++
13 files changed, 274 insertions(+), 3 deletions(-)
create mode 100644 ld/testsuite/ld-elf/pr25749-1.c
create mode 100644 ld/testsuite/ld-elf/pr25749-1a.c
create mode 100644 ld/testsuite/ld-elf/pr25749-1b.c
create mode 100644 ld/testsuite/ld-elf/pr25749-1b.err
create mode 100644 ld/testsuite/ld-elf/pr25749-1c.c
create mode 100644 ld/testsuite/ld-elf/pr25749-2.c
create mode 100644 ld/testsuite/ld-elf/pr25749-2a.s
create mode 100644 ld/testsuite/ld-elf/pr25749-2b.s
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index eb7e1f8b34..c0998d3212 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -2212,6 +2212,10 @@ elf_i386_relocate_section (bfd *output_bfd,
continue;
}
+ if (!_bfd_elf_x86_valid_reloc_p (input_section, info, rel, sec,
+ h, sym, symtab_hdr, howto))
+ return FALSE;
+
eh = (struct elf_x86_link_hash_entry *) h;
/* Since STT_GNU_IFUNC symbol must go through PLT, we handle
@@ -2704,7 +2708,7 @@ elf_i386_relocate_section (bfd *output_bfd,
|| is_vxworks_tls)
break;
- if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type,
+ if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, sec,
FALSE, resolved_to_zero,
(r_type == R_386_PC32)))
{
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 90e2702334..e3e6378741 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -2530,6 +2530,10 @@ elf_x86_64_relocate_section (bfd *output_bfd,
continue;
}
+ if (!_bfd_elf_x86_valid_reloc_p (input_section, info, rel, sec,
+ h, sym, symtab_hdr, howto))
+ return FALSE;
+
if (rel->r_addend == 0 && !ABI_64_P (output_bfd))
{
if (r_type == R_X86_64_64)
@@ -3175,7 +3179,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
&& (X86_PCREL_TYPE_P (r_type)
|| X86_SIZE_TYPE_P (r_type)));
- if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type,
+ if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, sec,
need_copy_reloc_in_pie,
resolved_to_zero, FALSE))
{
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 108e04a158..64e8170244 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -952,6 +952,59 @@ _bfd_x86_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
return _bfd_elf_link_check_relocs (abfd, info);
}
+bfd_boolean
+_bfd_elf_x86_valid_reloc_p (asection *input_section,
+ struct bfd_link_info *info,
+ const Elf_Internal_Rela *rel,
+ asection *sec,
+ struct elf_link_hash_entry *h,
+ Elf_Internal_Sym *sym,
+ Elf_Internal_Shdr *symtab_hdr,
+ const reloc_howto_type *howto)
+{
+ bfd_boolean valid_p = TRUE;
+
+ /* Check If relocation against absolute symbol is valid in PIC. */
+ if (bfd_link_pic (info)
+ && bfd_is_abs_section (sec)
+ && (h == NULL || SYMBOL_REFERENCES_LOCAL_P (info, h)))
+ {
+ const struct elf_backend_data *bed
+ = get_elf_backend_data (input_section->owner);
+ unsigned int r_type = ELF32_R_TYPE (rel->r_info);
+
+ /* Only allow S - A relocations against absolute symbol. */
+ if (bed->target_id == X86_64_ELF_DATA)
+ valid_p = (r_type == R_X86_64_64
+ || r_type == R_X86_64_32
+ || r_type == R_X86_64_16
+ || r_type == R_X86_64_8);
+ else
+ valid_p = (r_type == R_386_32
+ || r_type == R_386_16
+ || r_type == R_386_8);
+
+ if (!valid_p)
+ {
+ const char *name;
+ if (h)
+ name = h->root.root.string;
+ else
+ name = bfd_elf_sym_name (input_section->owner, symtab_hdr,
+ sym, NULL);
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: in relocation %s against absolute symbol `%s' "
+ "at %#" PRIx64 " in section `%pA' is disallowed"),
+ input_section->owner, howto->name, name,
+ (uint64_t) rel->r_offset, input_section);
+ bfd_set_error (bfd_error_bad_value);
+ }
+ }
+
+ return valid_p;
+}
+
/* Set the sizes of the dynamic sections. */
bfd_boolean
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index bef17dc2ba..8a2731a194 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -120,10 +120,11 @@
relocations against resolved undefined weak symbols in PIE, except
when PC32_RELOC is TRUE. Undefined weak symbol is bound locally
when PIC is false. */
-#define GENERATE_DYNAMIC_RELOCATION_P(INFO, EH, R_TYPE, \
+#define GENERATE_DYNAMIC_RELOCATION_P(INFO, EH, R_TYPE, SEC, \
NEED_COPY_RELOC_IN_PIE, \
RESOLVED_TO_ZERO, PC32_RELOC) \
((bfd_link_pic (INFO) \
+ && !bfd_is_abs_section (SEC) \
&& !(NEED_COPY_RELOC_IN_PIE) \
&& ((EH) == NULL \
|| ((ELF_ST_VISIBILITY ((EH)->elf.other) == STV_DEFAULT \
@@ -652,6 +653,11 @@ extern int _bfd_x86_elf_compare_relocs
extern bfd_boolean _bfd_x86_elf_link_check_relocs
(bfd *, struct bfd_link_info *);
+extern bfd_boolean _bfd_elf_x86_valid_reloc_p
+ (asection *, struct bfd_link_info *, const Elf_Internal_Rela *,
+ asection *, struct elf_link_hash_entry *, Elf_Internal_Sym *,
+ Elf_Internal_Shdr *, const reloc_howto_type *);
+
extern bfd_boolean _bfd_x86_elf_size_dynamic_sections
(bfd *, struct bfd_link_info *);
diff --git a/ld/testsuite/ld-elf/linux-x86.exp b/ld/testsuite/ld-elf/linux-x86.exp
index 63a321b966..f34158d0b5 100644
--- a/ld/testsuite/ld-elf/linux-x86.exp
+++ b/ld/testsuite/ld-elf/linux-x86.exp
@@ -115,3 +115,138 @@ elfedit_test "--disable-x86-feature shstk" x86-feature-1 x86-feature-1c
elfedit_test "--disable-x86-feature ibt" x86-feature-1 x86-feature-1d
elfedit_test "--enable-x86-feature ibt --enable-x86-feature shstk" \
x86-feature-1 x86-feature-1e
+
+proc check_pr25749a {testname srcfilea srcfileb cflags ldflags lderror} {
+ global objcopy
+ global srcdir
+ global subdir
+
+ if { [istarget "i?86-*-linux*"] } {
+ set output_arch "i386:i386"
+ set output_target "elf32-i386"
+ } else {
+ set output_arch "i386:x86-64"
+ if {[istarget "x86_64-*-linux*-gnux32"]} {
+ set output_target "elf32-x86-64"
+ } else {
+ set output_target "elf64-x86-64"
+ }
+ }
+
+ exec cp $srcdir/$subdir/$srcfilea $srcfilea
+ set pr25749_bin "$objcopy -B $output_arch -I binary -O $output_target $srcfilea tmpdir/pr25749-bin.o"
+ send_log "$pr25749_bin\n"
+ set got [remote_exec host "$pr25749_bin"]
+ if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
+ send_log "$got\n"
+ fail "Convert $srcfilea to $output_target"
+ return
+ }
+
+ if {"$lderror" == ""} {
+ run_ld_link_exec_tests [list \
+ [list \
+ "Run ${testname}a ($ldflags $cflags)" \
+ "$ldflags tmpdir/pr25749-bin.o" \
+ "" \
+ [list $srcfilea $srcfileb]\
+ "${testname}a" \
+ "pass.out" \
+ "$cflags" \
+ ] \
+ ]
+ } else {
+ run_cc_link_tests [list \
+ [list \
+ "Build $testname ($ldflags $cflags)" \
+ "$ldflags tmpdir/pr25749-bin.o" \
+ "$cflags" \
+ [list $srcfilea $srcfileb]\
+ [list [list error_output $lderror]] \
+ "$testname" \
+ ] \
+ ]
+ }
+}
+
+check_pr25749a "pr25749-1a" "pr25749-1.c" "pr25749-1a.c" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+check_pr25749a "pr25749-1a" "pr25749-1.c" "pr25749-1a.c" "-fPIE" "-pie" ""
+check_pr25749a "pr25749-1b" "pr25749-1.c" "pr25749-1b.c" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+check_pr25749a "pr25749-1b" "pr25749-1.c" "pr25749-1b.c" "-fPIE" "-pie" "pr25749-1b.err"
+check_pr25749a "pr25749-1c" "pr25749-1.c" "pr25749-1c.c" "-fPIC" "-shared" "pr25749-1b.err"
+check_pr25749a "pr25749-2a" "pr25749-2.c" "pr25749-2a.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+check_pr25749a "pr25749-2a" "pr25749-2.c" "pr25749-2a.s" "-fPIE" "-pie" ""
+check_pr25749a "pr25749-2b" "pr25749-2.c" "pr25749-2b.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+check_pr25749a "pr25749-2b" "pr25749-2.c" "pr25749-2b.s" "-fPIE" "-pie" ""
+
+proc check_pr25749b {testname srcfilea srcfileb cflags ldflags lderror} {
+ global objcopy
+ global srcdir
+ global subdir
+
+ if { [istarget "i?86-*-linux*"] } {
+ set output_arch "i386:i386"
+ set output_target "elf32-i386"
+ } else {
+ set output_arch "i386:x86-64"
+ if {[istarget "x86_64-*-linux*-gnux32"]} {
+ set output_target "elf32-x86-64"
+ } else {
+ set output_target "elf64-x86-64"
+ }
+ }
+
+ exec cp $srcdir/$subdir/$srcfilea $srcfilea
+ set pr25749_bin "$objcopy -B $output_arch -I binary -O $output_target $srcfilea tmpdir/pr25749-bin.o"
+ send_log "$pr25749_bin\n"
+ set got [remote_exec host "$pr25749_bin"]
+ if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
+ send_log "$got\n"
+ fail "Convert $srcfilea to $output_target"
+ return
+ }
+
+ if {"$lderror" == ""} {
+ run_cc_link_tests [list \
+ [list \
+ "Build lib${testname}.so ($ldflags $cflags)" \
+ "-shared tmpdir/pr25749-bin.o" \
+ "-fPIC" \
+ [list $srcfileb] \
+ "" \
+ "lib${testname}.so" \
+ ] \
+ ]
+ run_ld_link_exec_tests [list \
+ [list \
+ "Run ${testname}b ($ldflags $cflags)" \
+ "$ldflags -Wl,--no-as-needed tmpdir/lib${testname}.so" \
+ "" \
+ [list $srcfilea]\
+ "${testname}b" \
+ "pass.out" \
+ "$cflags" \
+ ] \
+ ]
+ } else {
+ run_cc_link_tests [list \
+ [list \
+ "Build $testname ($ldflags $cflags)" \
+ "$ldflags tmpdir/pr25749-bin.o" \
+ "$cflags" \
+ [list $srcfilea $srcfileb]\
+ [list [list error_output $lderror]] \
+ "$testname" \
+ ] \
+ ]
+ }
+}
+
+check_pr25749b "pr25749-1a" "pr25749-1.c" "pr25749-1a.c" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+check_pr25749b "pr25749-1a" "pr25749-1.c" "pr25749-1a.c" "-fPIE" "-pie" ""
+check_pr25749b "pr25749-1b" "pr25749-1.c" "pr25749-1b.c" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+check_pr25749b "pr25749-1b" "pr25749-1.c" "pr25749-1b.c" "-fPIE" "-pie" ""
+check_pr25749b "pr25749-2a" "pr25749-2.c" "pr25749-2a.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+check_pr25749b "pr25749-2a" "pr25749-2.c" "pr25749-2a.s" "-fPIE" "-pie" ""
+check_pr25749b "pr25749-2b" "pr25749-2.c" "pr25749-2b.s" "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" ""
+check_pr25749b "pr25749-2b" "pr25749-2.c" "pr25749-2b.s" "-fPIE" "-pie" ""
diff --git a/ld/testsuite/ld-elf/pr25749-1.c b/ld/testsuite/ld-elf/pr25749-1.c
new file mode 100644
index 0000000000..5b37af08c6
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749-1.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <bfd_stdint.h>
+
+extern intptr_t size (void);
+
+int
+main ()
+{
+ if (size () == 147)
+ printf ("PASS\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-elf/pr25749-1a.c b/ld/testsuite/ld-elf/pr25749-1a.c
new file mode 100644
index 0000000000..775623b8c9
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749-1a.c
@@ -0,0 +1,11 @@
+#include <bfd_stdint.h>
+
+extern void *_binary_pr25749_1_c_start;
+extern void *_binary_pr25749_1_c_end;
+
+intptr_t
+size (void)
+{
+ return ((intptr_t) &_binary_pr25749_1_c_end
+ - (intptr_t) &_binary_pr25749_1_c_start);
+}
diff --git a/ld/testsuite/ld-elf/pr25749-1b.c b/ld/testsuite/ld-elf/pr25749-1b.c
new file mode 100644
index 0000000000..f02a408700
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749-1b.c
@@ -0,0 +1,9 @@
+#include <bfd_stdint.h>
+
+extern void *_binary_pr25749_1_c_size;
+
+intptr_t
+size (void)
+{
+ return (intptr_t) &_binary_pr25749_1_c_size;
+}
diff --git a/ld/testsuite/ld-elf/pr25749-1b.err b/ld/testsuite/ld-elf/pr25749-1b.err
new file mode 100644
index 0000000000..bb389172f1
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749-1b.err
@@ -0,0 +1,3 @@
+#...
+.*: .* against absolute symbol `_binary_pr25749_1_c_size' .* is disallowed
+#pass
diff --git a/ld/testsuite/ld-elf/pr25749-1c.c b/ld/testsuite/ld-elf/pr25749-1c.c
new file mode 100644
index 0000000000..f2847d7f62
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749-1c.c
@@ -0,0 +1,9 @@
+#include <bfd_stdint.h>
+
+extern void *_binary_pr25749_1_c_size __attribute__ ((visibility("hidden")));
+
+intptr_t
+size (void)
+{
+ return (intptr_t) &_binary_pr25749_1_c_size;
+}
diff --git a/ld/testsuite/ld-elf/pr25749-2.c b/ld/testsuite/ld-elf/pr25749-2.c
new file mode 100644
index 0000000000..820bebc167
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749-2.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <bfd_stdint.h>
+
+extern intptr_t size;
+
+int
+main ()
+{
+ if (size == 137)
+ printf ("PASS\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-elf/pr25749-2a.s b/ld/testsuite/ld-elf/pr25749-2a.s
new file mode 100644
index 0000000000..df486fe329
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749-2a.s
@@ -0,0 +1,6 @@
+ .data
+ .globl size
+ .type size, %object
+size:
+ .dc.a _binary_pr25749_2_c_size
+ .size size, .-size
diff --git a/ld/testsuite/ld-elf/pr25749-2b.s b/ld/testsuite/ld-elf/pr25749-2b.s
new file mode 100644
index 0000000000..ba82c450bc
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr25749-2b.s
@@ -0,0 +1,7 @@
+ .data
+ .hidden _binary_pr25749_2_c_size
+ .globl size
+ .type size, %object
+size:
+ .dc.a _binary_pr25749_2_c_size
+ .size size, .-size
--
2.25.1
next reply other threads:[~2020-03-31 4:43 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-31 4:43 H.J. Lu [this message]
2020-03-31 6:17 ` Fangrui Song
2020-03-31 14:31 ` H.J. Lu
2020-03-31 23:25 ` V3 " H.J. Lu
2020-04-01 3:30 ` V4 " H.J. Lu
2020-04-01 14:06 ` V5 " H.J. Lu
2020-04-01 21:28 ` V6 " H.J. Lu
2020-04-02 3:24 ` Alan Modra
2020-04-02 11:54 ` H.J. Lu
2020-04-02 14:10 ` H.J. Lu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200331044350.808132-1-hjl.tools@gmail.com \
--to=hjl.tools@gmail.com \
--cc=binutils@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).