* [PATCH] x86: Properly handle function pointer reference
@ 2022-04-27 23:06 H.J. Lu
2022-04-28 15:51 ` H.J. Lu
0 siblings, 1 reply; 2+ messages in thread
From: H.J. Lu @ 2022-04-27 23:06 UTC (permalink / raw)
To: binutils
Update
commit ebb191adac4ab45498dec0bfaac62f0a33537ba4
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.
---
bfd/elf32-i386.c | 41 ++++++++++++-----------
bfd/elf64-x86-64.c | 40 +++++++++++-----------
ld/testsuite/ld-x86-64/protected-func-3.c | 41 +++++++++++++++++++++++
ld/testsuite/ld-x86-64/x86-64.exp | 18 ++++++++++
4 files changed, 102 insertions(+), 38 deletions(-)
create mode 100644 ld/testsuite/ld-x86-64/protected-func-3.c
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index fb5ed161f50..b034154fb97 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -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;
+ }
}
}
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 6cebc7ca2b3..6d69d6141ee 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -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;
+ }
}
}
diff --git a/ld/testsuite/ld-x86-64/protected-func-3.c b/ld/testsuite/ld-x86-64/protected-func-3.c
new file mode 100644
index 00000000000..bbf433b2462
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/protected-func-3.c
@@ -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;
+}
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index f337b485901..0a2f847ee79 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -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" \
--
2.35.1
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] x86: Properly handle function pointer reference
2022-04-27 23:06 [PATCH] x86: Properly handle function pointer reference H.J. Lu
@ 2022-04-28 15:51 ` H.J. Lu
0 siblings, 0 replies; 2+ messages in thread
From: H.J. Lu @ 2022-04-28 15:51 UTC (permalink / raw)
To: binutils
On Wed, Apr 27, 2022 at 4:06 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> Update
>
> commit ebb191adac4ab45498dec0bfaac62f0a33537ba4
> 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.
> ---
> bfd/elf32-i386.c | 41 ++++++++++++-----------
> bfd/elf64-x86-64.c | 40 +++++++++++-----------
> ld/testsuite/ld-x86-64/protected-func-3.c | 41 +++++++++++++++++++++++
> ld/testsuite/ld-x86-64/x86-64.exp | 18 ++++++++++
> 4 files changed, 102 insertions(+), 38 deletions(-)
> create mode 100644 ld/testsuite/ld-x86-64/protected-func-3.c
>
> diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
> index fb5ed161f50..b034154fb97 100644
> --- a/bfd/elf32-i386.c
> +++ b/bfd/elf32-i386.c
> @@ -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;
> + }
> }
> }
>
> diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
> index 6cebc7ca2b3..6d69d6141ee 100644
> --- a/bfd/elf64-x86-64.c
> +++ b/bfd/elf64-x86-64.c
> @@ -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;
> + }
> }
> }
>
> diff --git a/ld/testsuite/ld-x86-64/protected-func-3.c b/ld/testsuite/ld-x86-64/protected-func-3.c
> new file mode 100644
> index 00000000000..bbf433b2462
> --- /dev/null
> +++ b/ld/testsuite/ld-x86-64/protected-func-3.c
> @@ -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;
> +}
> diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
> index f337b485901..0a2f847ee79 100644
> --- a/ld/testsuite/ld-x86-64/x86-64.exp
> +++ b/ld/testsuite/ld-x86-64/x86-64.exp
> @@ -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" \
> --
> 2.35.1
>
I am checking it in and will backport it to 2.38 branch.
--
H.J.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-04-28 15:52 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-27 23:06 [PATCH] x86: Properly handle function pointer reference H.J. Lu
2022-04-28 15:51 ` H.J. Lu
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).