mirror of
https://github.com/XunilGroup/XunilOS.git
synced 2026-04-25 11:49:03 +02:00
Add better register clobbering to syscall calling in libxunil, add header magic to verify each free/malloc/realloc/calloc statement, add our own memcpy, memcmp, memset, memmove
This commit is contained in:
Submodule user/apps/doomgeneric updated: f67aed3904...146c36bfda
@@ -539,7 +539,7 @@ unsafe extern "C" fn strdup(s: *const u8) -> *mut u8 {
|
||||
if memory.is_null() {
|
||||
return null_mut();
|
||||
}
|
||||
memcpy(memory, s, len + 1);
|
||||
unsafe { memcpy(memory, s, len + 1) };
|
||||
memory
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use core::{mem, ptr::null_mut, usize};
|
||||
use core::{ffi::c_int, mem, ptr::null_mut, usize};
|
||||
|
||||
use crate::{
|
||||
heap::{ALLOCATOR, LinkedNode},
|
||||
@@ -12,10 +12,15 @@ pub fn sbrk(increment: i64) -> isize {
|
||||
|
||||
const MAX_SIZE: u64 = 18446744073709551615;
|
||||
|
||||
const HEADER_MAGIC_ALLOC: u64 = 0xBADC0FFEE0DDF00D;
|
||||
const HEADER_MAGIC_FREE: u64 = 0xFEE1DEADCAFEBABE;
|
||||
|
||||
#[repr(C, align(16))]
|
||||
struct Header {
|
||||
size: usize,
|
||||
_pad: usize,
|
||||
magic: u64,
|
||||
_pad: u64,
|
||||
alloc_size: usize,
|
||||
region_size: usize,
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
@@ -34,7 +39,7 @@ pub extern "C" fn calloc(count: u64, size: u64) -> *mut u8 {
|
||||
return null_mut();
|
||||
}
|
||||
|
||||
memset(ptr, 0, total as usize);
|
||||
unsafe { memset(ptr, 0, total as usize) };
|
||||
ptr
|
||||
}
|
||||
|
||||
@@ -46,9 +51,18 @@ pub extern "C" fn free(ptr: *mut u8) {
|
||||
|
||||
unsafe {
|
||||
let header_ptr = (ptr as usize - mem::size_of::<Header>()) as *mut Header;
|
||||
let total = (*header_ptr).size;
|
||||
if (header_ptr as usize) & 0xF != 0 {
|
||||
core::hint::unreachable_unchecked();
|
||||
}
|
||||
|
||||
if (*header_ptr).magic != HEADER_MAGIC_ALLOC {
|
||||
return;
|
||||
}
|
||||
|
||||
let region_size = (*header_ptr).region_size;
|
||||
(*header_ptr).magic = HEADER_MAGIC_FREE;
|
||||
let mut allocator = ALLOCATOR.lock();
|
||||
allocator.add_free_memory_region(header_ptr as usize, total);
|
||||
allocator.add_free_memory_region(header_ptr as usize, region_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,8 +85,10 @@ pub extern "C" fn malloc(size: u64) -> *mut u8 {
|
||||
unsafe {
|
||||
let header_ptr = region.start as *mut Header;
|
||||
header_ptr.write(Header {
|
||||
size: region.end - region.start,
|
||||
magic: HEADER_MAGIC_ALLOC,
|
||||
_pad: 0,
|
||||
alloc_size: (region.end - region.start).saturating_sub(hdr),
|
||||
region_size: region.end - region.start,
|
||||
});
|
||||
return (region.start + hdr) as *mut u8;
|
||||
}
|
||||
@@ -111,30 +127,6 @@ pub extern "C" fn malloc(size: u64) -> *mut u8 {
|
||||
malloc(size)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn memcpy(dest_str: *mut u8, src_str: *const u8, n: usize) -> *mut u8 {
|
||||
unsafe { core::ptr::copy(src_str, dest_str, n) };
|
||||
dest_str
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn memset(dst: *mut u8, c: i64, n: usize) -> *mut u8 {
|
||||
if dst.is_null() || n == 0 {
|
||||
return dst;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let val = c as u8;
|
||||
let mut i = 0usize;
|
||||
while i < n {
|
||||
*dst.add(i) = val;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
dst
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn realloc(ptr: *mut u8, size: usize) -> *mut u8 {
|
||||
if size == 0 {
|
||||
@@ -149,10 +141,14 @@ pub unsafe extern "C" fn realloc(ptr: *mut u8, size: usize) -> *mut u8 {
|
||||
unsafe {
|
||||
let hdr = mem::size_of::<Header>();
|
||||
let header_ptr = (ptr as usize - hdr) as *mut Header;
|
||||
let total = (*header_ptr).size;
|
||||
let old_payload = total.saturating_sub(hdr);
|
||||
|
||||
if size <= old_payload {
|
||||
if (*header_ptr).magic != HEADER_MAGIC_ALLOC {
|
||||
return null_mut();
|
||||
}
|
||||
|
||||
let old_alloc_size = (*header_ptr).alloc_size;
|
||||
|
||||
if size <= old_alloc_size {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -161,8 +157,102 @@ pub unsafe extern "C" fn realloc(ptr: *mut u8, size: usize) -> *mut u8 {
|
||||
return null_mut();
|
||||
}
|
||||
|
||||
core::ptr::copy_nonoverlapping(ptr, new_ptr, old_payload);
|
||||
core::ptr::copy_nonoverlapping(ptr, new_ptr, old_alloc_size);
|
||||
free(ptr);
|
||||
new_ptr
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn memset(dest: *mut u8, c: c_int, n: usize) -> *mut u8 {
|
||||
if n == 0 {
|
||||
return dest;
|
||||
}
|
||||
if dest.is_null() {
|
||||
return null_mut();
|
||||
}
|
||||
|
||||
let byte = c as u8;
|
||||
let mut i = 0usize;
|
||||
while i < n {
|
||||
unsafe { core::ptr::write_volatile(dest.add(i), byte) };
|
||||
i += 1;
|
||||
}
|
||||
|
||||
dest
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
|
||||
if n == 0 {
|
||||
return dest;
|
||||
}
|
||||
if dest.is_null() || src.is_null() {
|
||||
return null_mut();
|
||||
}
|
||||
|
||||
let mut i = 0usize;
|
||||
while i < n {
|
||||
let v = unsafe { core::ptr::read_volatile(src.add(i)) };
|
||||
unsafe { core::ptr::write_volatile(dest.add(i), v) };
|
||||
i += 1;
|
||||
}
|
||||
|
||||
dest
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn memmove(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
|
||||
if n == 0 {
|
||||
return dest;
|
||||
}
|
||||
if dest.is_null() || src.is_null() {
|
||||
return null_mut();
|
||||
}
|
||||
|
||||
let dest_addr = dest as usize;
|
||||
let src_addr = src as usize;
|
||||
|
||||
if dest_addr == src_addr {
|
||||
return dest;
|
||||
}
|
||||
|
||||
if dest_addr < src_addr || dest_addr >= src_addr.saturating_add(n) {
|
||||
let mut i = 0usize;
|
||||
while i < n {
|
||||
let v = unsafe { core::ptr::read_volatile(src.add(i)) };
|
||||
unsafe { core::ptr::write_volatile(dest.add(i), v) };
|
||||
i += 1;
|
||||
}
|
||||
} else {
|
||||
let mut i = n;
|
||||
while i != 0 {
|
||||
i -= 1;
|
||||
let v = unsafe { core::ptr::read_volatile(src.add(i)) };
|
||||
unsafe { core::ptr::write_volatile(dest.add(i), v) };
|
||||
}
|
||||
}
|
||||
|
||||
dest
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn memcmp(a: *const u8, b: *const u8, n: usize) -> i32 {
|
||||
if n == 0 {
|
||||
return 0;
|
||||
}
|
||||
if a.is_null() || b.is_null() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let mut i = 0usize;
|
||||
while i < n {
|
||||
let av = unsafe { core::ptr::read_volatile(a.add(i)) };
|
||||
let bv = unsafe { core::ptr::read_volatile(b.add(i)) };
|
||||
if av != bv {
|
||||
return av as i32 - bv as i32;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
@@ -32,8 +32,7 @@ pub unsafe fn syscall0(num: usize) -> isize {
|
||||
"int 0x80",
|
||||
in("rax") num,
|
||||
lateout("rax") ret,
|
||||
out("rdi") _, out("rcx") _, out("rdx") _, out("rsi") _,
|
||||
out("r8") _, out("r9") _, out("r10") _, out("r11") _,
|
||||
clobber_abi("sysv64"),
|
||||
options(nostack)
|
||||
);
|
||||
}
|
||||
@@ -50,8 +49,7 @@ pub unsafe fn syscall1(num: usize, arg0: isize) -> isize {
|
||||
in("rax") num,
|
||||
in("rdi") arg0,
|
||||
lateout("rax") ret,
|
||||
out("rcx") _, out("rdx") _, out("rsi") _,
|
||||
out("r8") _, out("r9") _, out("r10") _, out("r11") _,
|
||||
clobber_abi("sysv64"),
|
||||
options(nostack)
|
||||
);
|
||||
}
|
||||
@@ -70,6 +68,7 @@ pub unsafe fn syscall3(num: usize, arg0: isize, arg1: isize, arg2: isize) -> isi
|
||||
in("rsi") arg1,
|
||||
in("rdx") arg2,
|
||||
lateout("rax") ret,
|
||||
clobber_abi("sysv64"),
|
||||
options(nostack)
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user