fix(linker): deref uninit TCB

The bug is described for `x86_64` and Linux but is the same for other architectures and on Redox.

`Tcb::current()` is used to retrieve the current TCB, which is done by by reading `fs:[0x10]`. The TCB layout describes that at offset `0x10`, there is `tcb_ptr: *mut GenericTcb<...>`, which is nothing more but a pointer to itself.

This is fine as otherwise a system call would be required to get the TCB (`arch_prctl(ARCH_GET_FS)` on Linux).

However, this is problematic as the function may be called when the FS base is not set, and in that case the expected output of the function should be [`None`], but we don't currently handle that.

To fix this, any code paths that maybe call this function on an uninitialized TCB are be switched to call `current_slow()`. Which just uses `arch_prctl(ARCH_GET_FS)` to get the FS base and check if it's non-zero.

Signed-off-by: Anhad Singh <andypython@protonmail.com>
This commit is contained in:
Anhad Singh
2024-11-25 16:09:06 +11:00
parent 00746c2566
commit 37dbf5cbb2
3 changed files with 45 additions and 5 deletions
+3 -3
View File
@@ -47,7 +47,7 @@ pub unsafe extern "C" fn dlopen(cfilename: *const c_char, flags: c_int) -> *mut
))
};
let tcb = match Tcb::current() {
let tcb = match Tcb::current_slow() {
Some(tcb) => tcb,
None => {
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
@@ -83,7 +83,7 @@ pub unsafe extern "C" fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *m
let symbol_str = str::from_utf8_unchecked(CStr::from_ptr(symbol).to_bytes());
let tcb = match Tcb::current() {
let tcb = match Tcb::current_slow() {
Some(tcb) => tcb,
None => {
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
@@ -110,7 +110,7 @@ pub unsafe extern "C" fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *m
#[no_mangle]
pub unsafe extern "C" fn dlclose(handle: *mut c_void) -> c_int {
let tcb = match Tcb::current() {
let tcb = match Tcb::current_slow() {
Some(tcb) => tcb,
None => {
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);