|
|
Message-ID:
<DS4PR01MB99445317F95516FC965800CDC3EA692@DS4PR01MB994453.prod.exchangelabs.com>
Date: Wed, 4 Nov 2026 03:31:35 +0000
From: "Puranam, Ananta Srikar" <srikar.puranam@....edu>
To: "musl@...ts.openwall.com" <musl@...ts.openwall.com>,
"dalias@...c.org"
<dalias@...c.org>
CC: "West, Emily" <emily.west1@....edu>, "Priya, Swarn" <swarn.priya@....edu>,
"Gao, Peng" <penggao@...edu>,
"Ammanaghatta Shivakumar, Basavesh"
<basavesh.shivakumar@....edu>
Subject: ldso: TLS alignment above page size, initial-exec TLS error name, and
malformed-ELF list
Hi Rich,
As discussed in the e_phentsize thread
(https://www.openwall.com/lists/musl/2026/11/03/5), here is everything
in one place. I checked the first two on master at 7813e911 on x86_64.
1. TLS alignment above the page size
A __thread variable aligned to 8 KiB or more, in a library or in the
program, is not placed at that alignment. In ldso/dynlink.c the static
TLS offset is chosen from the run-time address of the TLS image (line
1240 for the library, 1938 for the program) rather than from p_vaddr,
so it is only right when the module's base is a multiple of the TLS
alignment.
Test: the program and a DT_NEEDED library each have
__thread char big[64] __attribute__((aligned(ALIGN)));
plus some initialized __thread variables, linked with GNU ld, gold,
LLD and mold.
- The library's block is misaligned by 4096 to 28672 bytes for
ALIGN 8192 to 65536. The amount changes from run to run with the
load address; with ASLR off it is always 4096 at 8192.
- With LLD and mold at ALIGN 32768 and 65536, the program's own
initialized __thread variables read as 0, and so do the library's.
- glibc 2.43 places and initializes every one of these correctly.
I only tested the main thread.
2. Name in the initial-exec TLS error
The "initial-exec TLS resolves to dynamic definition" error in
do_relocs prints name, which is only set when sym_index is nonzero
(line 429). For the symbol-less TPOFF64 relocation a library gets for
its own static __thread variable, built with -ftls-model=initial-exec
and then dlopen'ed:
- master prints an empty name, or a stale one from an earlier
relocation (reg_next_instance from another library in my test);
- 1.2.5 prints garbage bytes here, and segfaulted inside dlopen on
Alpine 3.22.
The refusal itself is correct; only the name is wrong.
3. Malformed-ELF list, for later
These are all deliberately malformed files, and each one crashes or
misbehaves in dlopen. I have a reproducer for each if you ever want
it.
- PT_LOAD extent arithmetic not checked (p_offset/p_filesz/p_memsz):
crash in map_library
- PT_LOAD p_vaddr + p_memsz overflow: SIGBUS while clearing BSS
- PT_LOAD p_vaddr + p_memsz overflow: SIGBUS while scanning PT_DYNAMIC
- PT_LOAD with p_memsz 0 covering relocation targets: write through
an invalid address in do_relocs
- PT_TLS p_vaddr overflow: out-of-bounds read
- DT_RELA pointer far outside the image: read in do_relocs
- DT_RELR pointer far outside the image: read in do_relr_relocs
- dynamic symbol st_name far outside .dynstr: bad pointer passed to
find_sym
- DT_GNU_HASH pointer far outside the image: read in
gnu_lookup_filtered
- DT_VERSYM pointer far outside the image: read in gnu_lookup
The relocation table sizes that wrap around (DT_RELASZ, DT_RELRSZ)
are in my earlier email "ldso: relocation table sizes can wrap around
in do_relocs".
Thanks,
Srikar
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.