From 75f6b9d64ebc92fbc2b02aea86a833c38100b59f Mon Sep 17 00:00:00 2001 From: Anhad Singh Date: Mon, 29 Dec 2025 17:08:33 +1100 Subject: [PATCH] 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 --- src/header/dl-tls/mod.rs | 31 ++++++++++++++++++++----------- src/ld_so/dso.rs | 3 ++- src/ld_so/mod.rs | 5 +++-- src/ld_so/tcb.rs | 12 +++++++----- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src/header/dl-tls/mod.rs b/src/header/dl-tls/mod.rs index 819121204b..3a5140d8f7 100644 --- a/src/header/dl-tls/mod.rs +++ b/src/header/dl-tls/mod.rs @@ -1,14 +1,17 @@ //! dl-tls implementation for Redox #![deny(unsafe_op_in_unsafe_fn)] +// FIXME(andypython): remove this when #![allow(warnings, unused_variables)] is +// dropped from src/lib.rs. +#![warn(warnings, unused_variables)] -use core::{alloc::Layout, arch::global_asm}; - -use alloc::alloc::alloc_zeroed; +use alloc::alloc::alloc; +use core::{alloc::Layout, ptr}; use crate::{ld_so::tcb::Tcb, platform::types::*}; #[repr(C)] +#[allow(non_camel_case_types)] pub struct dl_tls_index { pub ti_module: usize, pub ti_offset: usize, @@ -18,7 +21,7 @@ pub struct dl_tls_index { pub unsafe extern "C" fn __tls_get_addr(ti: *mut dl_tls_index) -> *mut c_void { let tcb = unsafe { Tcb::current().unwrap() }; let ti = unsafe { &*ti }; - let masters = unsafe { tcb.masters().unwrap() }; + let masters = tcb.masters().unwrap(); trace!( "__tls_get_addr({:p}: {:#x}, {:#x}, masters_len={}, dtv_len={})", @@ -40,15 +43,21 @@ pub unsafe extern "C" fn __tls_get_addr(ti: *mut dl_tls_index) -> *mut c_void { // Allocate TLS for module. let master = &masters[dtv_index]; - // FIXME(andypython): master.align - let layout = unsafe { - Layout::from_size_align_unchecked(master.offset /* aligned ph.p_memsz */, 16) + let module_tls = unsafe { + // FIXME(andypython): master.align + let layout = Layout::from_size_align_unchecked(master.segment_size, 16); + let ptr = alloc(layout); + + ptr::copy_nonoverlapping(master.ptr, ptr, master.image_size); + ptr::write_bytes( + ptr.add(master.image_size), + 0, + master.segment_size - master.image_size, + ); + + ptr }; - let module_tls = unsafe { alloc_zeroed(layout) }; - - unsafe { core::ptr::copy_nonoverlapping(master.ptr, module_tls, master.len) }; - // Set the DTV entry. tcb.dtv_mut()[dtv_index] = module_tls; } diff --git a/src/ld_so/dso.rs b/src/ld_so/dso.rs index 44c85f5c26..2fe3fdd495 100644 --- a/src/ld_so/dso.rs +++ b/src/ld_so/dso.rs @@ -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); diff --git a/src/ld_so/mod.rs b/src/ld_so/mod.rs index 9e75a79394..d16913edf9 100644 --- a/src/ld_so/mod.rs +++ b/src/ld_so/mod.rs @@ -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"); diff --git a/src/ld_so/tcb.rs b/src/ld_so/tcb.rs index 2375ce1228..c3ea48ac33 100644 --- a/src/ld_so/tcb.rs +++ b/src/ld_so/tcb.rs @@ -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() };