[v2,4/4] Update tests for protected data and function symbols

Message ID 20210624134938.2025098-5-hjl.tools@gmail.com
State Superseded
Headers
Series Implement indirect external access marker |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent
dj/TryBot-32bit success None

Commit Message

H.J. Lu June 24, 2021, 1:49 p.m. UTC
  Protected data and function symbols don't work well without
-fno-direct-extern-access:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37611
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=44166

1. Compile tst-protected1[ab].c and tst-protected1mod[ab].c with
-fno-direct-extern-access if possible so that GOT entries are used
for undefined data accesses.
2. Add tests for protected function pointers.
3. Build tst-prelink.c with direct external access to keep COPY
relocation.
---
 elf/Makefile              |  54 ++++++++++++++++
 elf/tst-protected1moda.c  |  10 +--
 elf/tst-protected1modb.c  |   4 +-
 elf/tst-protected2a.c     | 130 ++++++++++++++++++++++++++++++++++++++
 elf/tst-protected2apie.c  |   1 +
 elf/tst-protected2b.c     | 121 +++++++++++++++++++++++++++++++++++
 elf/tst-protected2bpie.c  |   1 +
 elf/tst-protected2mod.h   |  35 ++++++++++
 elf/tst-protected2moda.c  |  52 +++++++++++++++
 elf/tst-protected2moda2.c |  41 ++++++++++++
 elf/tst-protected2modb.c  |  45 +++++++++++++
 elf/tst-protected2modb2.c |  28 ++++++++
 12 files changed, 512 insertions(+), 10 deletions(-)
 create mode 100644 elf/tst-protected2a.c
 create mode 100644 elf/tst-protected2apie.c
 create mode 100644 elf/tst-protected2b.c
 create mode 100644 elf/tst-protected2bpie.c
 create mode 100644 elf/tst-protected2mod.h
 create mode 100644 elf/tst-protected2moda.c
 create mode 100644 elf/tst-protected2moda2.c
 create mode 100644 elf/tst-protected2modb.c
 create mode 100644 elf/tst-protected2modb2.c
  

Patch

diff --git a/elf/Makefile b/elf/Makefile
index 38d08e03b8..dc1a073db8 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -367,15 +367,59 @@  tests += tst-protected1a tst-protected1b
 $(objpfx)tst-protected1a: $(addprefix $(objpfx),tst-protected1moda.so tst-protected1modb.so)
 $(objpfx)tst-protected1b: $(addprefix $(objpfx),tst-protected1modb.so tst-protected1moda.so)
 tst-protected1modb.so-no-z-defs = yes
+ifeq (yes,$(have-fno-direct-extern-access))
+CFLAGS-tst-protected1a.c += -fno-direct-extern-access
+CFLAGS-tst-protected1b.c += -fno-direct-extern-access
+CFLAGS-tst-protected1moda.c += -fno-direct-extern-access
+CFLAGS-tst-protected1modb.c += -fno-direct-extern-access
+else
 # These tests fail with GCC versions prior to 5.1 and with some versions
 # of binutils.  See https://sourceware.org/bugzilla/show_bug.cgi?id=17709
 # and https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65248 for details.
 # Perhaps in future we can make these XFAILs conditional on some detection
 # of compiler/linker behavior/version.
+# NB: These tests pass with -fno-direct-extern-access when GOT entries
+# are used for undefined data accesses.
 test-xfail-tst-protected1a = yes
 test-xfail-tst-protected1b = yes
 endif
+ifeq (yes,$(have-z-indirect-extern-access))
+LDFLAGS-tst-protected1moda.so += -Wl,-z,indirect-extern-access
+LDFLAGS-tst-protected1modb.so += -Wl,-z,indirect-extern-access
+endif
+endif
 ifeq (yesyes,$(have-fpie)$(build-shared))
+ifeq (yes,$(have-z-indirect-extern-access))
+modules-names += tst-protected2moda tst-protected2modb
+tests += tst-protected2a tst-protected2b
+tests += tst-protected2apie tst-protected2bpie
+tests-pie += tst-protected2apie tst-protected2bpie
+test-extras += tst-protected2moda2 tst-protected2modb2
+extra-test-objs += tst-protected2moda2.os tst-protected2modb2.os
+LDFLAGS-tst-protected2moda.so += -Wl,-z,indirect-extern-access
+LDFLAGS-tst-protected2modb.so += -Wl,-z,indirect-extern-access
+CFLAGS-tst-protected2apie.c += $(PIE-ccflag)
+CFLAGS-tst-protected2bpie.c += $(PIE-ccflag)
+ifeq (yes,$(have-fno-direct-extern-access))
+CFLAGS-tst-protected2a.c += -fno-direct-extern-access
+CFLAGS-tst-protected2b.c += -fno-direct-extern-access
+CFLAGS-tst-protected2moda.c += -fno-direct-extern-access
+CFLAGS-tst-protected2moda2.c += -fno-direct-extern-access
+CFLAGS-tst-protected2modb.c += -fno-direct-extern-access
+CFLAGS-tst-protected2modb2.c += -fno-direct-extern-access
+else
+# These non-PIE tests fail when GOT entries are not used for undefined
+# function pointers.
+test-xfail-tst-protected2a = yes
+test-xfail-tst-protected2b = yes
+endif
+$(objpfx)tst-protected2moda.so: $(objpfx)tst-protected2moda2.os
+$(objpfx)tst-protected2modb.so: $(objpfx)tst-protected2modb2.os
+$(objpfx)tst-protected2a: $(addprefix $(objpfx),tst-protected2moda.so tst-protected2modb.so)
+$(objpfx)tst-protected2b: $(addprefix $(objpfx),tst-protected2modb.so tst-protected2moda.so)
+$(objpfx)tst-protected2apie: $(addprefix $(objpfx),tst-protected2moda.so tst-protected2modb.so)
+$(objpfx)tst-protected2bpie: $(addprefix $(objpfx),tst-protected2modb.so tst-protected2moda.so)
+endif
 modules-names += tst-piemod1
 tests += tst-pie1 tst-pie2 tst-dlopen-pie tst-dlopen-tlsmodid-pie \
   tst-dlopen-self-pie
@@ -469,6 +513,16 @@  tests += tst-prelink
 tests-internal += tst-prelink-cmp
 # Don't compile tst-prelink.c with PIE for GLOB_DAT relocation.
 CFLAGS-tst-prelink.c += -fno-pie
+ifeq ($(have-fno-direct-extern-access),yes)
+# Compile tst-prelink.c with -fdirect-extern-acces to keepp COPY
+# relocation.
+CFLAGS-tst-prelink.c += -fdirect-extern-access
+endif
+ifeq ($(have-z-indirect-extern-access),yes)
+# Link tst-prelink with -z noindirect-extern-access to keepp COPY
+# relocation.
+LDFLAGS-tst-prelink += -Wl,-z,noindirect-extern-access
+endif
 tst-prelink-no-pie = yes
 endif
 
diff --git a/elf/tst-protected1moda.c b/elf/tst-protected1moda.c
index eeb18306bb..3d0eb1e877 100644
--- a/elf/tst-protected1moda.c
+++ b/elf/tst-protected1moda.c
@@ -17,17 +17,13 @@ 
 
 #include "tst-protected1mod.h"
 
-int protected1 = 3;
+int protected1 __attribute__ ((visibility("protected"))) = 3;
 static int expected_protected1 = 3;
-int protected2 = 4;
+int protected2 __attribute__ ((visibility("protected"))) = 4;
 static int expected_protected2 = 4;
-int protected3 = 5;
+int protected3 __attribute__ ((visibility("protected"))) = 5;
 static int expected_protected3 = 5;
 
-asm (".protected protected1");
-asm (".protected protected2");
-asm (".protected protected3");
-
 void
 set_protected1a (int i)
 {
diff --git a/elf/tst-protected1modb.c b/elf/tst-protected1modb.c
index 2cb1e61b17..ca82c64689 100644
--- a/elf/tst-protected1modb.c
+++ b/elf/tst-protected1modb.c
@@ -19,11 +19,9 @@ 
 #include "tst-protected1mod.h"
 
 int protected1 = -3;
-int protected3 = -5;
+int protected3 __attribute__ ((visibility("protected"))) = -5;
 static int expected_protected3 = -5;
 
-asm (".protected protected3");
-
 void
 set_protected1b (int i)
 {
diff --git a/elf/tst-protected2a.c b/elf/tst-protected2a.c
new file mode 100644
index 0000000000..21b666e12b
--- /dev/null
+++ b/elf/tst-protected2a.c
@@ -0,0 +1,130 @@ 
+/* Test the protected visibility when main is linked with moda and modb
+   in that order:
+   1. Protected function symbols, protected1, protected2 and protected3,
+      defined in moda, are used in moda.
+   2. Protected function symbol, protected3, defined in modb, are used
+      in modb.
+   3. Symbol, protected1, defined in moda, is also used in main and modb.
+   4. Symbol, protected2, defined in main, is used in main.
+   5. Symbol, protected3, defined in moda, is also used in main.
+
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tst-protected2mod.h"
+
+int
+protected2 (void)
+{
+  return -1;
+}
+
+int
+__attribute__ ((weak, noclone, noinline))
+call_ptr (protected_func_type ptr)
+{
+  return ptr ();
+}
+
+int
+do_test (void)
+{
+  int res = 0;
+
+  /* Check if we get the same address for the protected function symbol.  */
+  protected_func_type ptr = protected1a_p ();
+  if (&protected1 != ptr)
+    {
+      puts ("`protected1' in main and moda doesn't have the same address");
+      res = 1;
+    }
+  ptr = protected1b_p ();
+  if (&protected1 != ptr)
+    {
+      puts ("`protected1' in main and modb doesn't have the same address");
+      res = 1;
+    }
+
+  /* Check if we get the right protected function symbol.  */
+  if (call_ptr (ptr) != 3)
+    {
+      puts ("`protected1' in main and moda doesn't return the same value");
+      res = 1;
+    }
+
+  /* Check if we get the right function defined in executable.  */
+  if (protected2 () != -1)
+    {
+      puts ("`protected2' in main returns the wrong value");
+      res = 1;
+    }
+
+  /* Check `protected1' in moda.  */
+  if (!check_protected1 ())
+    {
+      puts ("`protected1' in moda returns the wrong value");
+      res = 1;
+    }
+
+  /* Check `protected2' in moda.  */
+  if (!check_protected2 ())
+    {
+      puts ("`protected2' in moda returns the wrong value");
+      res = 1;
+    }
+
+  /* Check if we get the same address for the protected function symbol.  */
+  if (&protected3 != protected3a_p ())
+    {
+      puts ("`protected3' in main and moda doesn't have the same address");
+      res = 1;
+    }
+  if (&protected3 == protected3b_p ())
+    {
+      puts ("`protected3' in main and modb has the same address");
+      res = 1;
+    }
+
+  /* Check if we get the right value for the protected data symbol.  */
+  if (protected3 () != 5)
+    {
+      puts ("`protected3' in main and moda doesn't return the same value");
+      res = 1;
+    }
+
+  /* Check `protected3' in moda.  */
+  if (!check_protected3a ())
+    {
+      puts ("`protected3' in moda has the wrong value");
+      res = 1;
+    }
+
+  /* Check `protected3' in modb.  */
+  if (!check_protected3b ())
+    {
+      puts ("`protected3' in modb has the wrong value");
+      res = 1;
+    }
+
+  return res;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-protected2apie.c b/elf/tst-protected2apie.c
new file mode 100644
index 0000000000..28a7aa3d1a
--- /dev/null
+++ b/elf/tst-protected2apie.c
@@ -0,0 +1 @@ 
+#include "tst-protected2a.c"
diff --git a/elf/tst-protected2b.c b/elf/tst-protected2b.c
new file mode 100644
index 0000000000..500323e33f
--- /dev/null
+++ b/elf/tst-protected2b.c
@@ -0,0 +1,121 @@ 
+/* Test the protected visibility when main is linked with modb and moda
+   in that order:
+   1. Protected function symbols, protected1, protected2 and protected3,
+      defined in moda, are used in moda.
+   2. Protected function symbol, protected3, defined in modb, are used
+      in modb.
+   3. Symbol, protected1, defined in modb, is used in main and modb.
+   4. Symbol, protected2, defined in main, is used in main.
+   5. Symbol, protected3, defined in modb, is also used in main.
+
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tst-protected2mod.h"
+
+int
+protected2 (void)
+{
+  return -1;
+}
+
+int
+do_test (void)
+{
+  int res = 0;
+
+  /* Check if we get the same address for the protected data symbol.  */
+  if (&protected1 == protected1a_p ())
+    {
+      puts ("`protected1' in main and moda has the same address");
+      res = 1;
+    }
+  if (&protected1 != protected1b_p ())
+    {
+      puts ("`protected1' in main and modb doesn't have the same address");
+      res = 1;
+    }
+
+  /* Check if we get the right protected function symbol.  */
+  if (protected1 () != -3)
+    {
+      puts ("`protected1' in main and modb doesn't return the same value");
+      res = 1;
+    }
+
+  /* Check if we get the right function defined in executable.  */
+  if (protected2 () != -1)
+    {
+      puts ("`protected2' in main returns the wrong value");
+      res = 1;
+    }
+
+  /* Check `protected1' in moda.  */
+  if (!check_protected1 ())
+    {
+      puts ("`protected1' in moda returns the wrong value");
+      res = 1;
+    }
+
+  /* Check `protected2' in moda.  */
+  if (!check_protected2 ())
+    {
+      puts ("`protected2' in moda returns the wrong value");
+      res = 1;
+    }
+
+  /* Check if we get the same address for the protected function symbol.  */
+  if (&protected3 == protected3a_p ())
+    {
+      puts ("`protected3' in main and moda has the same address");
+      res = 1;
+    }
+  if (&protected3 != protected3b_p ())
+    {
+      puts ("`protected3' in main and modb doesn't have the same address");
+      res = 1;
+    }
+
+  /* Check if we get the right protected function symbol.  */
+  if (protected3 () != -5)
+    {
+      puts ("`protected3' in main and modb doesn't return the same value");
+      res = 1;
+    }
+
+  /* Check `protected3' in moda.  */
+  if (!check_protected3a ())
+    {
+      puts ("`protected3' in moda returns the wrong value");
+      res = 1;
+    }
+
+  /* Check `protected3' in modb.  */
+  if (!check_protected3b ())
+    {
+      puts ("`protected3' in modb returns the wrong value");
+      res = 1;
+    }
+
+  return res;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-protected2bpie.c b/elf/tst-protected2bpie.c
new file mode 100644
index 0000000000..8dcfbd04cb
--- /dev/null
+++ b/elf/tst-protected2bpie.c
@@ -0,0 +1 @@ 
+#include "tst-protected2b.c"
diff --git a/elf/tst-protected2mod.h b/elf/tst-protected2mod.h
new file mode 100644
index 0000000000..feb28ab0d5
--- /dev/null
+++ b/elf/tst-protected2mod.h
@@ -0,0 +1,35 @@ 
+/* Test protected function symbols.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* Prototypes for the functions in the DSOs.  */
+extern int protected1 (void);
+extern int protected2 (void);
+extern int protected3 (void);
+
+typedef int (*protected_func_type) (void);
+
+extern protected_func_type protected1a_p (void);
+extern protected_func_type protected1b_p (void);
+
+extern int check_protected1 (void);
+extern int check_protected2 (void);
+
+extern int check_protected3a (void);
+extern protected_func_type protected3a_p (void);
+extern int check_protected3b (void);
+extern protected_func_type protected3b_p (void);
diff --git a/elf/tst-protected2moda.c b/elf/tst-protected2moda.c
new file mode 100644
index 0000000000..db04e8dfb9
--- /dev/null
+++ b/elf/tst-protected2moda.c
@@ -0,0 +1,52 @@ 
+/* Test protected function symbols.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include "tst-protected2mod.h"
+
+__attribute__ ((visibility("protected")))
+int
+protected1 (void)
+{
+  return 3;
+}
+
+__attribute__ ((visibility("protected")))
+int
+protected2 (void)
+{
+  return 4;
+}
+
+__attribute__ ((visibility("protected")))
+int
+protected3 (void)
+{
+  return 5;
+}
+
+protected_func_type
+protected1a_p (void)
+{
+  return &protected1;
+}
+
+protected_func_type
+protected3a_p (void)
+{
+  return &protected3;
+}
diff --git a/elf/tst-protected2moda2.c b/elf/tst-protected2moda2.c
new file mode 100644
index 0000000000..fae72177f9
--- /dev/null
+++ b/elf/tst-protected2moda2.c
@@ -0,0 +1,41 @@ 
+/* Test protected function symbols.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include "tst-protected2mod.h"
+
+extern int protected1 (void) __attribute__ ((visibility("protected")));
+extern int protected2 (void) __attribute__ ((visibility("protected")));
+extern int protected3 (void) __attribute__ ((visibility("protected")));
+
+int
+check_protected1 (void)
+{
+  return protected1 () == 3;
+}
+
+int
+check_protected2 (void)
+{
+  return protected2 () == 4;
+}
+
+int
+check_protected3a (void)
+{
+  return protected3 () == 5;
+}
diff --git a/elf/tst-protected2modb.c b/elf/tst-protected2modb.c
new file mode 100644
index 0000000000..3c5063f0c3
--- /dev/null
+++ b/elf/tst-protected2modb.c
@@ -0,0 +1,45 @@ 
+/* Test protected function symbols.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+#include "tst-protected2mod.h"
+
+int
+protected1 (void)
+{
+  return -3;
+}
+
+__attribute__ ((visibility("protected")))
+int
+protected3 (void)
+{
+  return -5;
+}
+
+protected_func_type
+protected1b_p (void)
+{
+  return &protected1;
+}
+
+protected_func_type
+protected3b_p (void)
+{
+  return &protected3;
+}
diff --git a/elf/tst-protected2modb2.c b/elf/tst-protected2modb2.c
new file mode 100644
index 0000000000..b21b827134
--- /dev/null
+++ b/elf/tst-protected2modb2.c
@@ -0,0 +1,28 @@ 
+/* Test protected function symbols.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+#include "tst-protected2mod.h"
+
+extern int protected3 (void) __attribute__ ((visibility("protected")));
+
+int
+check_protected3b (void)
+{
+  return protected3 () == -5;
+}