fix(dl-tls): TLS overallocation

* `offset` is the offset in TLS to copy initial data to NOT the segment
  size
* Only zero the region which is required to be zeroed

Signed-off-by: Anhad Singh <andypython@protonmail.com>
This commit is contained in:
Anhad Singh
2025-12-29 17:08:33 +11:00
parent be446db7c3
commit 75f6b9d64e
4 changed files with 32 additions and 19 deletions
+2 -1
View File
@@ -612,7 +612,8 @@ impl DSO {
};
tcb_master = Some(Master {
ptr,
len: ph.p_filesz(endian) as usize,
image_size: ph.p_filesz(endian) as usize,
segment_size: ph.p_memsz(endian) as usize,
offset: tls_offset + ph.p_memsz(endian) as usize,
});
trace!(" tcb master {:x?}", tcb_master);
+3 -2
View File
@@ -33,7 +33,8 @@ pub use generic_rt::{ExpectTlsFree, panic_notls};
static mut STATIC_TCB_MASTER: Master = Master {
ptr: ptr::null_mut(),
len: 0,
image_size: 0,
segment_size: 0,
offset: 0,
};
@@ -112,7 +113,7 @@ pub fn static_init(
unsafe {
STATIC_TCB_MASTER.ptr = p_vaddr as *const u8;
STATIC_TCB_MASTER.len = p_filesz;
STATIC_TCB_MASTER.image_size = p_filesz;
STATIC_TCB_MASTER.offset = valign;
let tcb = Tcb::new(vsize).expect_notls("failed to allocate TCB");
+7 -5
View File
@@ -26,7 +26,8 @@ pub struct Master {
/// Pointer to initial data
pub ptr: *const u8,
/// Length of initial data in bytes
pub len: usize,
pub image_size: usize,
pub segment_size: usize,
/// Offset in TLS to copy initial data to
pub offset: usize,
}
@@ -34,7 +35,7 @@ pub struct Master {
impl Master {
/// The initial data for this TLS region
pub unsafe fn data(&self) -> &'static [u8] {
unsafe { slice::from_raw_parts(self.ptr, self.len) }
unsafe { slice::from_raw_parts(self.ptr, self.image_size) }
}
}
@@ -157,13 +158,14 @@ impl Tcb {
for master in masters
.iter()
.skip(self.num_copied_masters)
.filter(|master| master.len != 0)
.filter(|master| master.image_size != 0)
{
let range = if cfg!(any(target_arch = "x86", target_arch = "x86_64")) {
// x86{_64} TLS layout is backwards
self.tls_len - master.offset..self.tls_len - master.offset + master.len
self.tls_len - master.offset
..self.tls_len - master.offset + master.image_size
} else {
master.offset..master.offset + master.len
master.offset..master.offset + master.image_size
};
if let Some(tls_data) = tls.get_mut(range) {
let data = unsafe { master.data() };