[PATCH] elf: Support vDSO with more than one PT_LOAD with v_addr starting at 0 (BZ 32583)

Adhemerval Zanella adhemerval.zanella@linaro.org
Tue Dec 9 21:35:13 GMT 2025


The setup_vdso assumes that vDSO will contain only one PT_LOAD segment
and that 0 is the sentinel for the start mapping address. Although the
kernel avoids adding more than one PT_LOAD to avoid compatibility
issues, there is no impending issue that prevents glibc from supporting
vDSO with multiple PT_LOAD (as some wrapper tools do [1]).

To support multiple PT_LOAD segments, replace the sentinel with a bool
to indicate that the VMA start has already been set.

Testing is really tricky, since the bug report does not indicate which
tool was used to trigger the issue, nor a runtime that provides a vDSO
with multiple PT_LOAD. I had to modify the qemu user with a custom
script to create 2 PT_LOAD sections, remove some checks that avoid
creating the vDSO object, and remove the load bias adjustment in
load_elf_vdso. I could not come up with an easy test case to integrate
with glibc.

Checked on aarch64-linux-gnu.

https://sourceware.org/bugzilla/show_bug.cgi?id=32583#c2
---
 elf/setup-vdso.h | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/elf/setup-vdso.h b/elf/setup-vdso.h
index 935d9e3baf..6e974875e7 100644
--- a/elf/setup-vdso.h
+++ b/elf/setup-vdso.h
@@ -31,6 +31,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)),
      mapped and relocated it normally.  */
   struct link_map *l = _dl_new_object ((char *) "", "", lt_library, NULL,
 				       __RTLD_VDSO, LM_ID_BASE);
+  bool l_addr_set = false;
   if (__glibc_likely (l != NULL))
     {
       l->l_phdr = ((const void *) GLRO(dl_sysinfo_dso)
@@ -47,8 +48,11 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)),
 	    }
 	  else if (ph->p_type == PT_LOAD)
 	    {
-	      if (! l->l_addr)
-		l->l_addr = ph->p_vaddr;
+	      if (!l_addr_set)
+		{
+		  l->l_addr = ph->p_vaddr;
+		  l_addr_set = true;
+		}
 	      if (ph->p_vaddr + ph->p_memsz >= l->l_map_end)
 		l->l_map_end = ph->p_vaddr + ph->p_memsz;
 	    }
-- 
2.43.0



More information about the Libc-alpha mailing list