diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2022-02-09 15:51:22 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2022-02-11 10:24:54 -0800 |
commit | ebb191adac4ab45498dec0bfaac62f0a33537ba4 (patch) | |
tree | 34999ecb8d01541fde94b8a70b3164d80682a516 /bfd | |
parent | 29ba33db77f22a54d97db90cb87c39126efad3db (diff) | |
download | gdb-ebb191adac4ab45498dec0bfaac62f0a33537ba4.zip gdb-ebb191adac4ab45498dec0bfaac62f0a33537ba4.tar.gz gdb-ebb191adac4ab45498dec0bfaac62f0a33537ba4.tar.bz2 |
x86: Disallow invalid relocation against protected symbol
I am checking this into master and will backport it to 2.38 branch.
H.J
----
On x86, GCC 12 supports -mno-direct-extern-access to enable canonical
reference to protected function and disable copy relocation. With
-mno-direct-extern-access, the canonical protected function symbols must
be accessed via canonical reference and the protected data symbols in
shared libraries are non-copyable. Under glibc 2.35, non-canonical
reference to the canonical protected function will get the run-time error:
./y: internal_f: ./libfoo.so: non-canonical reference to canonical protected function
and copy relocations against the non-copyable protected symbols will get
the run-time error:
./x: internal_i: ./libfoo.so: copy relocation against non-copyable protected symbol
Update x86 linker to disallow non-canonical reference to the canonical
protected function:
ld: plt.o: non-canonical reference to canonical protected function `internal_f' in libfoo.so
ld: failed to set dynamic section sizes: bad value
and copy relocation against the non-copyable protected symbol:
ld: main.o: copy relocation against non-copyable protected symbol `internal_i' in libfoo.so
at link-time.
bfd/
PR ld/28875
* elf-properties.c (_bfd_elf_parse_gnu_properties): Don't skip
shared libraries for GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS.
* elf32-i386.c (elf_i386_scan_relocs): Disallow non-canonical
reference to canonical protected function.
* elf64-x86-64.c (elf_x86_64_scan_relocs): Likewise.
* elfxx-x86.c (elf_x86_allocate_dynrelocs): Don't allow copy
relocation against non-copyable protected symbol.
ld/
PR ld/28875
* testsuite/ld-i386/i386.exp: Check non-canonical reference to
canonical protected function and check copy relocation against
non-copyable protected symbol.
* testsuite/ld-i386/pr21997-1.err: New file.
* testsuite/ld-i386/pr28875.err: Likewise.
* testsuite/ld-i386/pr28875a.c: Likewise.
* testsuite/ld-i386/pr28875b.c: Likewise.
* testsuite/ld-x86-64/pr21997-1a.err: Updated.
* testsuite/ld-x86-64/pr21997-1b.err: Likewise.
* testsuite/ld-x86-64/pr28875-data.err: New file.
* testsuite/ld-x86-64/pr28875-func.err: Likewise.
* testsuite/ld-x86-64/x86-64.exp: Check non-canonical reference
to canonical protected function and check copy relocation against
non-copyable protected symbol.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/elf-properties.c | 5 | ||||
-rw-r--r-- | bfd/elf32-i386.c | 17 | ||||
-rw-r--r-- | bfd/elf64-x86-64.c | 17 | ||||
-rw-r--r-- | bfd/elfxx-x86.c | 18 |
4 files changed, 53 insertions, 4 deletions
diff --git a/bfd/elf-properties.c b/bfd/elf-properties.c index bf4f70d..d67aadd 100644 --- a/bfd/elf-properties.c +++ b/bfd/elf-properties.c @@ -195,14 +195,11 @@ _bfd_elf_parse_gnu_properties (bfd *abfd, Elf_Internal_Note *note) prop = _bfd_elf_get_property (abfd, type, datasz); prop->u.number |= bfd_h_get_32 (abfd, ptr); prop->pr_kind = property_number; - if ((abfd->flags & DYNAMIC) == 0 - && type == GNU_PROPERTY_1_NEEDED + if (type == GNU_PROPERTY_1_NEEDED && ((prop->u.number & GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS) != 0)) { - /* NB: Skip the shared library since it may not be - the same at run-time. */ elf_has_indirect_extern_access (abfd) = true; /* GNU_PROPERTY_NO_COPY_ON_PROTECTED is implied. */ elf_has_no_copy_on_protected (abfd) = true; diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 25977cc..fb5ed16 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1779,6 +1779,23 @@ elf_i386_scan_relocs (bfd *abfd, func_pointer_ref = true; } + if (h->pointer_equality_needed + && h->type == STT_FUNC + && eh->def_protected + && elf_has_indirect_extern_access (h->root.u.def.section->owner)) + { + /* Disallow non-canonical reference to canonical + protected function. */ + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: non-canonical reference to canonical " + "protected function `%s' in %pB"), + abfd, h->root.root.string, + h->root.u.def.section->owner); + bfd_set_error (bfd_error_bad_value); + goto error_return; + } + if (!func_pointer_ref) { /* If this reloc is in a read-only section, we might diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 02ca552..b5718e7 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -2223,6 +2223,23 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info, func_pointer_ref = true; } + if (h->pointer_equality_needed + && h->type == STT_FUNC + && eh->def_protected + && elf_has_indirect_extern_access (h->root.u.def.section->owner)) + { + /* Disallow non-canonical reference to canonical + protected function. */ + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: non-canonical reference to canonical " + "protected function `%s' in %pB"), + abfd, h->root.root.string, + h->root.u.def.section->owner); + bfd_set_error (bfd_error_bad_value); + goto error_return; + } + if (!func_pointer_ref) { /* If this reloc is in a read-only section, we might diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index d00dc45..acb2cc8 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -524,6 +524,24 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) { asection *sreloc; + if (eh->def_protected + && elf_has_no_copy_on_protected (h->root.u.def.section->owner)) + { + /* Disallow copy relocation against non-copyable protected + symbol. */ + asection *s = p->sec->output_section; + if (s != NULL && (s->flags & SEC_READONLY) != 0) + { + info->callbacks->einfo + /* xgettext:c-format */ + (_("%F%P: %pB: copy relocation against non-copyable " + "protected symbol `%s' in %pB\n"), + p->sec->owner, h->root.root.string, + h->root.u.def.section->owner); + return false; + } + } + sreloc = elf_section_data (p->sec)->sreloc; BFD_ASSERT (sreloc != NULL); |