mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 18:14:13 +08:00
x86: Properly handle function pointer reference
Update
commit ebb191adac
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Wed Feb 9 15:51:22 2022 -0800
x86: Disallow invalid relocation against protected symbol
to allow function pointer reference and make sure that PLT entry isn't
used for function reference due to function pointer reference.
bfd/
PR ld/29087
* elf32-i386.c (elf_i386_scan_relocs): Don't set
pointer_equality_needed nor check non-canonical reference for
function pointer reference.
* elf64-x86-64.c (elf_x86_64_scan_relocs): Likewise.
ld/
PR ld/29087
* testsuite/ld-x86-64/x86-64.exp: Run PR ld/29087 tests.
* testsuite/ld-x86-64/protected-func-3.c: New file.
This commit is contained in:
parent
9dd9f9ce1e
commit
68c4956b14
@ -1772,28 +1772,14 @@ elf_i386_scan_relocs (bfd *abfd,
|
||||
}
|
||||
else
|
||||
{
|
||||
h->pointer_equality_needed = 1;
|
||||
/* R_386_32 can be resolved at run-time. */
|
||||
/* R_386_32 can be resolved at run-time. Function
|
||||
pointer reference doesn't need PLT for pointer
|
||||
equality. */
|
||||
if (r_type == R_386_32
|
||||
&& (sec->flags & SEC_READONLY) == 0)
|
||||
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;
|
||||
else
|
||||
h->pointer_equality_needed = 1;
|
||||
}
|
||||
|
||||
if (!func_pointer_ref)
|
||||
@ -1815,6 +1801,23 @@ elf_i386_scan_relocs (bfd *abfd,
|
||||
if (!h->def_regular
|
||||
|| (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
|
||||
h->plt.refcount = 1;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2211,33 +2211,18 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
else if (r_type != R_X86_64_PC32_BND
|
||||
&& r_type != R_X86_64_PC64)
|
||||
{
|
||||
h->pointer_equality_needed = 1;
|
||||
/* At run-time, R_X86_64_64 can be resolved for both
|
||||
x86-64 and x32. But R_X86_64_32 and R_X86_64_32S
|
||||
can only be resolved for x32. */
|
||||
can only be resolved for x32. Function pointer
|
||||
reference doesn't need PLT for pointer equality. */
|
||||
if ((sec->flags & SEC_READONLY) == 0
|
||||
&& (r_type == R_X86_64_64
|
||||
|| (!ABI_64_P (abfd)
|
||||
&& (r_type == R_X86_64_32
|
||||
|| r_type == R_X86_64_32S))))
|
||||
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;
|
||||
else
|
||||
h->pointer_equality_needed = 1;
|
||||
}
|
||||
|
||||
if (!func_pointer_ref)
|
||||
@ -2259,6 +2244,23 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
if (!h->def_regular
|
||||
|| (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
|
||||
h->plt.refcount = 1;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
41
ld/testsuite/ld-x86-64/protected-func-3.c
Normal file
41
ld/testsuite/ld-x86-64/protected-func-3.c
Normal file
@ -0,0 +1,41 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "protected-func-1.h"
|
||||
|
||||
protected_func_type protected_func_1a_ptr = protected_func_1a;
|
||||
protected_func_type protected_func_1b_ptr = protected_func_1b;
|
||||
|
||||
int
|
||||
protected_func_1b (void)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
protected_func_1a ();
|
||||
protected_func_1b ();
|
||||
|
||||
/* Check if we get the same address for the protected function symbol. */
|
||||
if (protected_func_1a_ptr != protected_func_1a_p ())
|
||||
{
|
||||
puts ("'protected_func_1a' in main and shared library doesn't have same address");
|
||||
res = 1;
|
||||
}
|
||||
|
||||
/* Check if we get the different addresses for the protected function
|
||||
symbol. */
|
||||
if (protected_func_1b_ptr == protected_func_1b_p ())
|
||||
{
|
||||
puts ("'protected_func_1b' in main and shared library has same address");
|
||||
res = 1;
|
||||
}
|
||||
|
||||
if (!res)
|
||||
puts ("PASS");
|
||||
|
||||
return res;
|
||||
}
|
@ -1886,6 +1886,24 @@ if { [isnative] && [check_compiler_available] } {
|
||||
"pass.out" \
|
||||
"-fPIE" \
|
||||
] \
|
||||
[list \
|
||||
"Run protected-func-3a without PIE" \
|
||||
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/libprotected-func-2a.so" \
|
||||
"-Wa,-mx86-used-note=yes" \
|
||||
{ protected-func-3.c } \
|
||||
"protected-func-3a" \
|
||||
"pass.out" \
|
||||
"$NOPIE_CFLAGS" \
|
||||
] \
|
||||
[list \
|
||||
"Run protected-func-3b with PIE" \
|
||||
"-Wl,--no-as-needed -pie tmpdir/libprotected-func-2a.so" \
|
||||
"-Wa,-mx86-used-note=yes" \
|
||||
{ protected-func-3.c } \
|
||||
"protected-func-2b" \
|
||||
"pass.out" \
|
||||
"-fPIE" \
|
||||
] \
|
||||
[list \
|
||||
"Run protected-data-1a without PIE" \
|
||||
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/libprotected-data-1a.so" \
|
||||
|
Loading…
Reference in New Issue
Block a user