[PATCH] elf: Allow vDSO as a direct dependency (BZ 33335)

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Thu Dec 18 20:48:33 GMT 2025



On 18/12/25 12:23, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>> The vDSO is treated as a special link map, and using it as a direct
>> dependency shows two issues:
>>
>> 1. Binding uses the implicit vDSO provided by the kernel (even though a
>>    library is explicitly provided);
>> 2. And depending on how the binary is linked, it can cause loops that
>>    trigger an inconsistency during process startup.
> 
> What are the expected semantics if a library is provided?  Would we use
> it for clock_gettime etc. instead of the kernel-provided object?

The origin bug report is not fully clear [1], although the linked issue [2]
does hint that some project is providing fake vDSO object for specific
reasons [3].

I think using the provided vDSO symbol follows the principle of least surprise,
it is at least have a DT_NEEDED library where the dynamic loader is not using
such symbols.

[1] https://github.com/rust-lang/rust/issues/145854
[2] https://github.com/fortanix/rust-sgx/pull/804
[3] https://github.com/fortanix/rust-sgx/blob/master/intel-sgx/enclave-runner/src/tcs.rs

> 
>> diff --git a/elf/Makefile b/elf/Makefile
>> index 07b456f4f5..b2ed018b10 100644
>> --- a/elf/Makefile
>> +++ b/elf/Makefile
>> @@ -1447,7 +1447,18 @@ CFLAGS-tst-_dl_addr_inside_object.c += $(PIE-ccflag)
>>  endif
>>  
>>  ifeq ($(run-built-tests),yes)
>> -tests-special += $(objpfx)tst-origin.out
>> +tests-special += \
>> +  $(objpfx)tst-origin.out \
>> +  $(objpfx)tst-vdso-2.out \
>> +  # tests-special
>> +endif
>> +
>> +ifndef (,$(vdso-name))
>> +tests += tst-vdso-1
> 
> Confusion between ifndef and ifneq?
> (There are multiple occurrences of this.)

It should 'ifndef' indeed, ifneq does not see to work correctly. It
just that I used the way we define the 'ifneq' that make it confusing.
I will change to just:

  ifndef $(vdso-name)

> 
> If this lives in sysdeps/unix/sysv/linux/x86_64/Makefile, the check
> would be unnecessary.

And I am not sure what you are suggestion to live in x86_64/Makefile,
the tst-vdso* are ABI agnostic

> 
>> diff --git a/elf/dl-object.c b/elf/dl-object.c
>> index 51d3704edc..8325258c2f 100644
>> --- a/elf/dl-object.c
>> +++ b/elf/dl-object.c
>> @@ -98,6 +98,7 @@ _dl_new_object (char *realname, const char *libname, int type,
>>    new->l_real = new;
>>    new->l_symbolic_searchlist.r_list = (struct link_map **) ((char *) (new + 1)
>>  							    + audit_space);
>> +  new->l_vdso = !!(mode & __RTLD_VDSO);
>>  
>>    new->l_libname = newname
>>      = (struct libname_list *) (new->l_symbolic_searchlist.r_list + 1);
>> diff --git a/elf/linux-vdso.c b/elf/linux-vdso.c
>> new file mode 100644
>> index 0000000000..abbd88e3fb
> 
> I believe this should go under sysdeps/unix/sysv/linux.

I was in doubt whereas to put, but I think it makes sense.

> 
>> diff --git a/include/link.h b/include/link.h
>> index 78fa288b9d..78ce1edb26 100644
>> --- a/include/link.h
>> +++ b/include/link.h
>> @@ -213,6 +213,7 @@ struct link_map
>>  					       needs to process this
>>  					       lt_library map.  */
>>      unsigned int l_tls_in_slotinfo:1; /* TLS slotinfo updated in dlopen.  */
>> +    unsigned int l_vdso:1;  /* Nonzero if object refers to a vDSO.  */
>>  
>>      /* NODELETE status of the map.  Only valid for maps of type
>>         lt_loaded.  Lazy binding sets l_nodelete_active directly,
> 
> This starts a new byte.  I don't think this matters unless we want to
> backport this because we should not change the layout of struct link_map
> in a backport.
> 
> Looking at the existing bits, I think we could replace l_link_map with
> an lt_executable check if we ever need to backport this.  Or add a new
> lt_vdso type.

I think a lt_vdso would make sense here, it should not interfere with
other lt_type usage when vDSO is concerned. 

> 
>> diff --git a/sysdeps/unix/sysv/linux/aarch64/Makefile b/sysdeps/unix/sysv/linux/aarch64/Makefile
>> index 6741f8ec00..569f840e1e 100644
>> --- a/sysdeps/unix/sysv/linux/aarch64/Makefile
>> +++ b/sysdeps/unix/sysv/linux/aarch64/Makefile
>> @@ -158,3 +158,5 @@ endif
>>  
>>  abi-lp64-condition := !defined __AARCH64EB__
>>  abi-lp64_be-condition := defined __AARCH64EB__
>> +
>> +vdso-name := linux-vdso
> 
> Wouldn't this go into shlib-versions, something like this:
> 
> linux-vdso=linux-vdso.1
> 
> And then you'd use $(linux-vdso.so-version).  This may end up in
> <gnu/lib-names.h>, but I don't think that's necessarily a bad thing?
> It's ABI, after all.

I don't have a strong opinion, although it highly unusual to need the
vDSO names for dlfcn operation (as for other lib-names.h usage).  In
theory users may try to bypass libc.so, but it requires some extra
care like the powerpc64v1 idiosyncrasy where we need to synthesize the
ODP entry.  



More information about the Libc-alpha mailing list