public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [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).