]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
elf: Add optimization barrier for __ehdr_start and _end
authorH.J. Lu <hjl.tools@gmail.com>
Sun, 15 Jun 2025 03:38:54 +0000 (11:38 +0800)
committerH.J. Lu <hjl.tools@gmail.com>
Mon, 16 Jun 2025 00:43:40 +0000 (08:43 +0800)
rtld.c has

extern const ElfW(Ehdr) __ehdr_start attribute_hidden;
...
  _dl_rtld_map.l_map_start = (ElfW(Addr)) &__ehdr_start;
  _dl_rtld_map.l_map_end = (ElfW(Addr)) _end;

As

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

shows, compiler may generate run-time relocation on __ehdr_start with

movq .LC0(%rip), %xmm0
...
.section .data.rel.ro.local,"aw"
.align 8
.LC0:
.quad __ehdr_start

This won't work before run-time relocation is finished in rtld.c.  Add
optimization barrier to prevent run-time relocations against __ehdr_start
and _end.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
elf/rtld.c
sysdeps/x86_64/Makefile

index 8e8f0e6253acd9db48bd59c532eabbc5167306b0..e6a181dc310a080a8668ffc316f9a6818d0c0495 100644 (file)
@@ -477,7 +477,10 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
   _dl_setup_hash (&_dl_rtld_map);
   _dl_rtld_map.l_real = &_dl_rtld_map;
   _dl_rtld_map.l_map_start = (ElfW(Addr)) &__ehdr_start;
+  /* Prevent run-time relocations against __ehdr_start and _end.  */
+  asm ("" : "+g" (_dl_rtld_map.l_map_start));
   _dl_rtld_map.l_map_end = (ElfW(Addr)) _end;
+  asm ("" : "+g" (_dl_rtld_map.l_map_end));
   /* Copy the TLS related data if necessary.  */
 #ifndef DONT_USE_BOOTSTRAP_MAP
 # if NO_TLS_OFFSET != 0
index 5723ec18473bae55939e7e06699583a1526f5506..e8f8a52eeac4e5ad0e59df3ca8d507e0d16bef5a 100644 (file)
@@ -214,6 +214,24 @@ $(objpfx)tst-plt-rewrite2: $(objpfx)tst-plt-rewritemod2.so
 endif
 
 test-internal-extras += tst-gnu2-tls2mod1
+
+tests-special += $(objpfx)check-rtld.out
+
+$(objpfx)rtld.reloc: $(objpfx)rtld.os
+       @rm -f $@T
+       LC_ALL=C $(READELF) -rW $< > $@T
+       test -s $@T
+       mv -f $@T $@
+common-generated += $(objpfx)rtld.reloc
+
+# Verify that there are no run-time relocations against __ehdr_start nor
+# _end.
+$(objpfx)check-rtld.out: $(objpfx)rtld.reloc
+       LC_ALL=C; \
+       if grep -E "R_X86_64_64.*(__ehdr_start|_end)" $^ > $@; \
+         then false; else true; fi; \
+       $(evaluate-test)
+generated += check-rtld.out
 endif # $(subdir) == elf
 
 ifeq ($(subdir),csu)