aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2022-02-09 15:51:22 -0800
committerH.J. Lu <hjl.tools@gmail.com>2022-02-11 10:24:54 -0800
commitebb191adac4ab45498dec0bfaac62f0a33537ba4 (patch)
tree34999ecb8d01541fde94b8a70b3164d80682a516 /bfd
parent29ba33db77f22a54d97db90cb87c39126efad3db (diff)
downloadgdb-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.c5
-rw-r--r--bfd/elf32-i386.c17
-rw-r--r--bfd/elf64-x86-64.c17
-rw-r--r--bfd/elfxx-x86.c18
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);