public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: "H.J. Lu" <hjl.tools@gmail.com>
To: libc-alpha@sourceware.org
Subject: [PATCH v7 2/6] Add GLIBC_ABI_DT_RELR for DT_RELR support
Date: Thu, 31 Mar 2022 09:38:54 -0700	[thread overview]
Message-ID: <20220331163858.95516-3-hjl.tools@gmail.com> (raw)
In-Reply-To: <20220331163858.95516-1-hjl.tools@gmail.com>

The EI_ABIVERSION field of the ELF header in executables and shared
libraries can be bumped to indicate the minimum ABI requirement on the
dynamic linker.  However, EI_ABIVERSION in executables isn't checked by
the Linux kernel ELF loader nor the existing dynamic linker.  Executables
will crash mysteriously if the dynamic linker doesn't support the ABI
features required by the EI_ABIVERSION field.  The dynamic linker should
be changed to check EI_ABIVERSION in executables.

Add a glibc version, GLIBC_ABI_DT_RELR, to indicate DT_RELR support so
that the existing dynamic linkers will issue an error on executables with
GLIBC_ABI_DT_RELR dependency.  Issue an error if there is a DT_RELR entry
without GLIBC_ABI_DT_RELR dependency nor GLIBC_PRIVATE definition.

Support __placeholder_only_for_empty_version_map as the placeholder symbol
used only for empty version map to generate GLIBC_ABI_DT_RELR without any
symbols.
---
 elf/Makefile         | 14 ++++++++++++--
 elf/Versions         |  5 +++++
 elf/dl-version.c     | 33 +++++++++++++++++++++++++++++++--
 include/link.h       |  6 ++++++
 scripts/abilist.awk  |  2 ++
 scripts/versions.awk |  7 ++++++-
 6 files changed, 62 insertions(+), 5 deletions(-)

diff --git a/elf/Makefile b/elf/Makefile
index c96924e9c2..09d3d88336 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -1105,8 +1105,12 @@ $(eval $(call include_dsosort_tests,dso-sort-tests-1.def))
 $(eval $(call include_dsosort_tests,dso-sort-tests-2.def))
 endif
 
-check-abi: $(objpfx)check-abi-ld.out
-tests-special += $(objpfx)check-abi-ld.out
+check-abi: $(objpfx)check-abi-ld.out \
+	   $(objpfx)check-abi-version-libc.out
+tests-special += \
+  $(objpfx)check-abi-ld.out \
+  $(objpfx)check-abi-version-libc.out \
+# tests-special
 update-abi: update-abi-ld
 update-all-abi: update-all-abi-ld
 
@@ -2725,3 +2729,9 @@ $(objpfx)tst-p_align3: $(objpfx)tst-p_alignmod3.so
 $(objpfx)tst-p_align3.out: tst-p_align3.sh $(objpfx)tst-p_align3
 	$(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \
 	$(evaluate-test)
+
+$(objpfx)check-abi-version-libc.out: $(common-objpfx)libc.so
+	LC_ALL=C $(READELF) -V -W $< \
+		| sed -ne '/.gnu.version_d/, /.gnu.version_r/ p' \
+		| grep GLIBC_ABI_DT_RELR > $@; \
+	$(evaluate-test)
diff --git a/elf/Versions b/elf/Versions
index 8bed855d8c..a9ff278de7 100644
--- a/elf/Versions
+++ b/elf/Versions
@@ -23,6 +23,11 @@ libc {
   GLIBC_2.35 {
     _dl_find_object;
   }
+  GLIBC_ABI_DT_RELR {
+    # This symbol is used only for empty version map and will be removed
+    # by scripts/versions.awk.
+    __placeholder_only_for_empty_version_map;
+  }
   GLIBC_PRIVATE {
     # functions used in other libraries
     __libc_early_init;
diff --git a/elf/dl-version.c b/elf/dl-version.c
index b47bd91727..720ec596a5 100644
--- a/elf/dl-version.c
+++ b/elf/dl-version.c
@@ -214,12 +214,20 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
 	      while (1)
 		{
 		  /* Match the symbol.  */
+		  const char *string = strtab + aux->vna_name;
 		  result |= match_symbol (DSO_FILENAME (map->l_name),
 					  map->l_ns, aux->vna_hash,
-					  strtab + aux->vna_name,
-					  needed->l_real, verbose,
+					  string, needed->l_real, verbose,
 					  aux->vna_flags & VER_FLG_WEAK);
 
+		  if (map->l_abi_version == lav_none
+		      /* 0xfd0e42: _dl_elf_hash ("GLIBC_ABI_DT_RELR").  */
+		      && aux->vna_hash == 0xfd0e42
+		      && __glibc_likely (strcmp (string,
+						 "GLIBC_ABI_DT_RELR")
+					 == 0))
+		    map->l_abi_version = lav_dt_relr_ref;
+
 		  /* Compare the version index.  */
 		  if ((unsigned int) (aux->vna_other & 0x7fff) > ndx_high)
 		    ndx_high = aux->vna_other & 0x7fff;
@@ -253,6 +261,16 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
       ent = (ElfW(Verdef) *) (map->l_addr + def->d_un.d_ptr);
       while (1)
 	{
+	  /* 0x0963cf85: _dl_elf_hash ("GLIBC_PRIVATE").  */
+	  if (ent->vd_hash == 0x0963cf85)
+	    {
+	      ElfW(Verdaux) *aux = (ElfW(Verdaux) *) ((char *) ent
+						      + ent->vd_aux);
+	      if (__glibc_likely (strcmp ("GLIBC_PRIVATE",
+					  strtab + aux->vda_name) == 0))
+		map->l_abi_version = lav_private_def;
+	    }
+
 	  if ((unsigned int) (ent->vd_ndx & 0x7fff) > ndx_high)
 	    ndx_high = ent->vd_ndx & 0x7fff;
 
@@ -352,6 +370,17 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
 	}
     }
 
+  /* Issue an error if there is a DT_RELR entry without GLIBC_ABI_DT_RELR
+     dependency nor GLIBC_PRIVATE definition.  */
+  if (map->l_info[DT_RELR] != NULL
+      && __glibc_unlikely (map->l_abi_version == lav_none))
+    {
+      _dl_exception_create
+	(&exception, DSO_FILENAME (map->l_name),
+	 N_("DT_RELR without GLIBC_ABI_DT_RELR dependency"));
+      goto call_error;
+    }
+
   return result;
 }
 
diff --git a/include/link.h b/include/link.h
index 03db14c7b0..8ec5e35cf2 100644
--- a/include/link.h
+++ b/include/link.h
@@ -177,6 +177,12 @@ struct link_map
 	lt_library,		/* Library needed by main executable.  */
 	lt_loaded		/* Extra run-time loaded shared object.  */
       } l_type:2;
+    enum			/* ABI dependency of this object.  */
+      {
+	lav_none,		/* No ABI dependency.  */
+	lav_dt_relr_ref,	/* Need GLIBC_ABI_DT_RELR.  */
+	lav_private_def		/* Define GLIBC_PRIVATE.  */
+      } l_abi_version:2;
     unsigned int l_relocated:1;	/* Nonzero if object's relocations done.  */
     unsigned int l_init_called:1; /* Nonzero if DT_INIT function called.  */
     unsigned int l_global:1;	/* Nonzero if object in _dl_global_scope.  */
diff --git a/scripts/abilist.awk b/scripts/abilist.awk
index 24a34ccbed..6cc7af6ac8 100644
--- a/scripts/abilist.awk
+++ b/scripts/abilist.awk
@@ -55,6 +55,8 @@ $2 == "g" || $2 == "w" && (NF == 7 || NF == 8) {
   # caused STV_HIDDEN symbols to appear in .dynsym, though that is useless.
   if (NF > 7 && $7 == ".hidden") next;
 
+  if (version ~ /^GLIBC_ABI_/ && !include_abi_version) next;
+
   if (version == "GLIBC_PRIVATE" && !include_private) next;
 
   desc = "";
diff --git a/scripts/versions.awk b/scripts/versions.awk
index 357ad1355e..d70b07bd1a 100644
--- a/scripts/versions.awk
+++ b/scripts/versions.awk
@@ -185,8 +185,13 @@ END {
 	closeversion(oldver, veryoldver);
 	veryoldver = oldver;
       }
-      printf("%s {\n  global:\n", $2) > outfile;
       oldver = $2;
+      # Skip the placeholder symbol used only for empty version map.
+      if ($3 == "__placeholder_only_for_empty_version_map;") {
+	printf("%s {\n", $2) > outfile;
+	continue;
+      }
+      printf("%s {\n  global:\n", $2) > outfile;
     }
     printf("   ") > outfile;
     for (n = 3; n <= NF; ++n) {
-- 
2.35.1


  parent reply	other threads:[~2022-03-31 16:39 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-31 16:38 [PATCH v7 0/6] Support DT_RELR relative relocation format H.J. Lu
2022-03-31 16:38 ` [PATCH v7 1/6] elf: Define DT_RELR related macros and types H.J. Lu
2022-04-04 15:46   ` Adhemerval Zanella
2022-04-09  0:19     ` Fangrui Song
2022-03-31 16:38 ` H.J. Lu [this message]
2022-04-04 15:55   ` [PATCH v7 2/6] Add GLIBC_ABI_DT_RELR for DT_RELR support Adhemerval Zanella
2022-04-13 16:46     ` H.J. Lu
2022-03-31 16:38 ` [PATCH v7 3/6] elf: Support DT_RELR relative relocation format [BZ #27924] H.J. Lu
2022-04-04 17:12   ` Adhemerval Zanella
2022-04-13 16:54     ` H.J. Lu
2022-03-31 16:38 ` [PATCH v7 4/6] elf: Properly handle zero DT_RELA/DT_REL values H.J. Lu
2022-04-04 17:13   ` Adhemerval Zanella
2022-03-31 16:38 ` [PATCH v7 5/6] Add --disable-default-dt-relr H.J. Lu
2022-04-04 18:15   ` Adhemerval Zanella
2022-03-31 16:38 ` [PATCH v7 6/6] NEWS: Mention DT_RELR support H.J. Lu
2022-04-04 18:16   ` Adhemerval Zanella
2022-04-09  0:16     ` Fangrui Song

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220331163858.95516-3-hjl.tools@gmail.com \
    --to=hjl.tools@gmail.com \
    --cc=libc-alpha@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).