Page MenuHomeFreeBSD

libc: Don't bias DTV entries by TLS_DTV_OFFSET
ClosedPublic

Authored by jrtc27 on May 5 2025, 11:18 PM.
Tags
None
Referenced Files
Unknown Object (File)
Tue, Jul 1, 8:19 AM
Unknown Object (File)
Sun, Jun 29, 4:00 AM
Unknown Object (File)
Fri, Jun 27, 10:32 PM
Unknown Object (File)
Thu, Jun 26, 4:08 PM
Unknown Object (File)
Tue, Jun 24, 3:08 PM
Unknown Object (File)
Thu, Jun 19, 12:13 AM
Unknown Object (File)
Tue, Jun 17, 1:08 PM
Unknown Object (File)
Mon, Jun 16, 10:46 PM
Subscribers

Details

Summary

PowerPC and RISC-V have a non-zero TLS_DTV_OFFSET. The intent behind
this in the design is that DTV entries are biased by this, as are (in
the other direction) the DTPOFF/DTPREL entries in the GOT. However, this
is pretty pointless in practice, and both FreeBSD and glibc's run-time
linkers don't bother to bias DTV entries, instead just adding the bias
back on at the end in tls_get_addr. In libc we also have a minimal
implementation of this for statically-linked binaries, which is only in
practice used for code compiled with -fPIC (not -fPIE) that is also
linked without TLS relaxation support. PowerPC supports linker
relaxation for TLS sequences, so this likely never gets hit there, but
RISC-V does not, and so easily does if you compile an executable with
-fPIC. In this implementation we add TLS_DTV_OFFSET both to the DTV
entries in
libc_allocate_tls and to the result of __tls_get_addr,
meaning that any TLS accesses using the General Dynamic model in static
binaries on RISC-V end up off by 0x800.

Historically this also did not matter as tls_get_addr was a stub that
always returned NULL, so although 6e16d0bc4376 ("Rework alignment
handling in
libc_allocate_tls() for Variant I of TLS layout.") added
this DTV implementation, nothing actually read the entries. However, now
it's a real implementation, and dl_iterate_phdr also now relies on it,
it does matter.

Fix this by not biasing the DTV entries, just like RTLD. We could
instead stop adding TLS_DTV_OFFSET in __tls_get_addr, but being
consistent between libc and RTLD seems better.

(Note this also applies to MIPS on stable/13)

Fixes: ca46b5698e8a ("libc: implement __tls_get_addr() for static binaries")
MFC after: 1 week

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable