kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit b11597609109b3ac2f2416582aaf1a2cdf9b4caf
parent dc1dc1f96640de20daa2a4b9accfb0a26b839218
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Tue, 16 Jun 2026 15:58:12 -0700

link: restrict coalesced PT_LOAD perms-union to R/W/X (exclude SF_TLS)

A coalesced PT_LOAD's flags must carry only the p_flags-relevant bits. The
emitter treats an SF_TLS-flagged PT_LOAD specially (p_memsz collapses to
file_size), and TLS sizing is owned by the dedicated PT_TLS segment, so OR-ing
SF_TLS into a PT_LOAD is never correct. Narrow the perms-union accordingly.
Defensive: the scripted layout does not currently route SF_TLS into a coalesced
section's perms (verified: a real .tdata coalesced into a flags-less PT_LOAD
keeps memsz>filesz), so this only sharpens intent with no observable change.

Diffstat:
Msrc/link/link_layout.c | 10+++++++---
1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/link/link_layout.c b/src/link/link_layout.c @@ -1546,9 +1546,13 @@ static void link_layout_sections_scripted(Linker* l, LinkImage* img, /* Bug 2: a FLAGS-less PHDRS PT_LOAD maps p_flags from seg->flags * (perms_to_pflags); a coalesced PT_LOAD must carry the UNION of all its * mapped sections' perms (GNU-ld behavior), not just the first section's - * (set once at segment creation). OR in this section's perms here. The - * load-bearing part is `perms` (SF_EXEC/SF_WRITE/SF_TLS). */ - seg->flags |= SF_ALLOC | perms; + * (set once at segment creation). Union only the p_flags-relevant bits + * (R/W/X) — a PT_LOAD's flags must never include SF_TLS, which the + * emitter treats specially (p_memsz collapses to file_size for SF_TLS + * segments); TLS sizing is owned by the dedicated PT_TLS segment. + * (Defensive: the scripted layout does not currently route SF_TLS into a + * coalesced section's perms, so this only narrows intent.) */ + seg->flags |= SF_ALLOC | (perms & (SF_EXEC | SF_WRITE)); } else { seg = &img->segments[img->nsegments]; memset(seg, 0, sizeof(*seg));