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:
+20
-11
@@ -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;
|
||||
}
|
||||
|
||||
+2
-1
@@ -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
@@ -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
@@ -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() };
|
||||
|
||||
Reference in New Issue
Block a user