[v2] Add GLIBC_ABI_VERSION_GEN2 for ABIVERSION

Message ID 20211123223053.3334224-1-hjl.tools@gmail.com
State Dropped
Headers
Series [v2] Add GLIBC_ABI_VERSION_GEN2 for ABIVERSION |

Checks

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

Commit Message

H.J. Lu Nov. 23, 2021, 10:30 p.m. UTC
  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_VERSION_GEN2, to mirror the EI_ABIVERSION
bump from the baseline ABI features so that the existing dynamic linkers
will issue an error on executables with GLIBC_ABI_VERSION_GEN2 depdendency.

A dummy symbol, __libc_abi_version_placeholder, is added since linker
won't create a symbol version node with an empty symbol list.
---
 elf/Makefile             | 19 ++++++++++++++++---
 elf/Versions             |  3 +++
 elf/libc-abi-version.c   | 21 +++++++++++++++++++++
 elf/libc-abi-version.exp |  1 +
 scripts/abilist.awk      |  2 ++
 5 files changed, 43 insertions(+), 3 deletions(-)
 create mode 100644 elf/libc-abi-version.c
 create mode 100644 elf/libc-abi-version.exp
  

Patch

diff --git a/elf/Makefile b/elf/Makefile
index 4723c159cb..5da419c0e5 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -25,7 +25,8 @@  headers		= elf.h bits/elfclass.h link.h bits/link.h bits/link_lavcurrent.h
 routines	= $(all-dl-routines) dl-support dl-iteratephdr \
 		  dl-addr dl-addr-obj enbl-secure dl-profstub \
 		  dl-origin dl-libc dl-sym dl-sysdep dl-error \
-		  dl-reloc-static-pie libc_early_init rtld_static_init
+		  dl-reloc-static-pie libc_early_init rtld_static_init \
+		  libc-abi-version
 
 # The core dynamic linking functions are in libc for the static and
 # profiled libraries.
@@ -517,8 +518,10 @@  $(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
 update-abi: update-abi-ld
 update-all-abi: update-all-abi-ld
 
@@ -1977,3 +1980,13 @@  $(objpfx)tst-ro-dynamic-mod.so: $(objpfx)tst-ro-dynamic-mod.os \
 	$(LINK.o) -nostdlib -nostartfiles -shared -o $@ \
 		-Wl,--script=tst-ro-dynamic-mod.map \
 		$(objpfx)tst-ro-dynamic-mod.os
+
+$(objpfx)check-abi-version-libc.out: libc-abi-version.exp \
+  $(objpfx)libc.symlist-abi-version
+	cmp $^ > $@; \
+	$(evaluate-test)
+
+$(objpfx)libc.symlist-abi-version: $(common-objpfx)libc.so
+	LC_ALL=C $(NM) -D $< | grep " GLIBC_ABI_VERSION_" \
+		| sed "s/^0\+/00000000/" > $@T
+	mv -f $@T $@
diff --git a/elf/Versions b/elf/Versions
index 775aab62af..f51e77ab8a 100644
--- a/elf/Versions
+++ b/elf/Versions
@@ -20,6 +20,9 @@  libc {
     __register_frame_info_table_bases; _Unwind_Find_FDE;
   }
 %endif
+  GLIBC_ABI_VERSION_GEN2 {
+    __libc_abi_version_placeholder;
+  }
   GLIBC_PRIVATE {
     # functions used in other libraries
     __libc_early_init;
diff --git a/elf/libc-abi-version.c b/elf/libc-abi-version.c
new file mode 100644
index 0000000000..9763f6b19d
--- /dev/null
+++ b/elf/libc-abi-version.c
@@ -0,0 +1,21 @@ 
+/* Placeholder definition for GLIBC_ABI_VERSION nodes.
+   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/>.  */
+
+#ifdef SHARED
+char __libc_abi_version_placeholder attribute_compat_data_section;
+#endif
diff --git a/elf/libc-abi-version.exp b/elf/libc-abi-version.exp
new file mode 100644
index 0000000000..64a97b8d6f
--- /dev/null
+++ b/elf/libc-abi-version.exp
@@ -0,0 +1 @@ 
+00000000 A GLIBC_ABI_VERSION_GEN2
diff --git a/scripts/abilist.awk b/scripts/abilist.awk
index 24a34ccbed..94ee8b0e0f 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_VERSION_/ && !include_abi_version) next;
+
   if (version == "GLIBC_PRIVATE" && !include_private) next;
 
   desc = "";