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.
This commit is contained in:
H.J. Lu 2022-02-09 15:51:22 -08:00
parent 29ba33db77
commit ebb191adac
14 changed files with 116 additions and 25 deletions

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -1288,6 +1288,30 @@ if { [isnative]
{} \
"pr22842.so" \
] \
[list \
"Build pr28875.so" \
"-shared -Wl,-z,indirect-extern-access" \
"-fPIC" \
{ pr28875a.c } \
{} \
"pr28875.so" \
] \
[list \
"Build pr28875" \
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr28875.so" \
"$NOPIE_CFLAGS" \
{ pr28875b.c } \
{{error_output "pr28875.err"}} \
"pr28875" \
] \
[list \
"Build pr21997-1" \
"$NOPIE_LDFLAGS -Wl,--no-as-needed,-z,notext tmpdir/pr21997-1.so" \
"$NOPIE_CFLAGS -Wa,-mx86-used-note=yes" \
{ pr21997-1b.c } \
{{error_output "pr21997-1.err"}} \
"pr21997-1" \
] \
]
run_ld_link_exec_tests [list \
@ -1343,15 +1367,6 @@ if { [isnative]
"pass.out" \
"-fPIC" \
] \
[list \
"Run pr21997-1" \
"$NOPIE_LDFLAGS -Wl,--no-as-needed,-z,notext tmpdir/pr21997-1.so" \
"-Wa,-mx86-used-note=yes" \
{ pr21997-1b.c } \
"pr21997-1" \
"pass.out" \
"$NOPIE_CFLAGS" \
] \
[list \
"Run pr21997-1 (PIC 1)" \
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr21997-1.so" \

View File

@ -0,0 +1,2 @@
.*: tmpdir/pr21997-1b.o: copy relocation against non-copyable protected symbol `protected' in tmpdir/pr21997-1.so
#...

View File

@ -0,0 +1,2 @@
.*: tmpdir/pr28875b.o: non-canonical reference to canonical protected function `internal_f' in tmpdir/pr28875.so
#...

View File

@ -0,0 +1,5 @@
__attribute__ ((visibility("protected")))
void
internal_f (void)
{
}

View File

@ -0,0 +1,7 @@
extern void internal_f (void);
int
main ()
{
return (int) &internal_f;
}

View File

@ -1,2 +1,2 @@
.*relocation R_X86_64_PC32 against protected symbol `protected' can not be used when making a P(D|I)E object; recompile with -fPIE
.*: tmpdir/pr21997-1b.o: copy relocation against non-copyable protected symbol `protected' in tmpdir/pr21997-1.so
#...

View File

@ -1,2 +1,2 @@
.*relocation R_X86_64_32S against protected symbol `protected' can not be used when making a P(D|I)E object; recompile with -fPIE
.*: tmpdir/pr21997-1c.o: copy relocation against non-copyable protected symbol `protected' in tmpdir/pr21997-1.so
#...

View File

@ -0,0 +1,2 @@
.*: tmpdir/protected-data-1b.o: copy relocation against non-copyable protected symbol `protected_data_1a' in tmpdir/libprotected-data-1b.so
#...

View File

@ -0,0 +1,2 @@
.*: tmpdir/protected-func-1b.o: non-canonical reference to canonical protected function `protected_func_1a' in tmpdir/libprotected-func-2b.so
#...

View File

@ -1381,6 +1381,14 @@ if { [isnative] && [check_compiler_available] } {
{{readelf -n indirect-extern-access.rd}} \
"libprotected-func-2b.so" \
] \
[list \
"Build protected-func-2 without PIE" \
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/libprotected-func-2b.so" \
"$NOPIE_CFLAGS -Wa,-mx86-used-note=yes" \
{ protected-func-1b.c } \
{{error_output "pr28875-func.err"}} \
"protected-func-2" \
] \
[list \
"Build libprotected-data-1a.so" \
"-shared -z noindirect-extern-access" \
@ -1402,7 +1410,7 @@ if { [isnative] && [check_compiler_available] } {
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/libprotected-data-1b.so" \
"$NOPIE_CFLAGS -Wa,-mx86-used-note=yes" \
{ protected-data-1b.c } \
{} \
{{error_output "pr28875-data.err"}} \
"protected-data-1" \
] \
[list \
@ -1468,6 +1476,14 @@ if { [isnative] && [check_compiler_available] } {
"-Wa,-mx86-used-note=yes" \
{ pr25416-5d.s } \
] \
[list \
"Build pr21997-1b" \
"$NOPIE_LDFLAGS -Wl,--no-as-needed,-z,notext tmpdir/pr21997-1.so" \
"$NOPIE_CFLAGS -Wa,-mx86-used-note=yes" \
{ pr21997-1c.c } \
{{error_output "pr21997-1b.err"}} \
"pr21997-1b" \
] \
]
run_ld_link_exec_tests [list \
@ -1480,15 +1496,6 @@ if { [isnative] && [check_compiler_available] } {
"pass.out" \
"$NOPIE_CFLAGS" \
] \
[list \
"Run pr21997-1b" \
"$NOPIE_LDFLAGS -Wl,--no-as-needed,-z,notext tmpdir/pr21997-1.so" \
"-Wa,-mx86-used-note=yes" \
{ pr21997-1c.c } \
"pr21997-1b" \
"pass.out" \
"$NOPIE_CFLAGS" \
] \
[list \
"Run pr25416-5a (GDesc -> IE -maddress-mode=short)" \
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr25416-5b.so" \