From 28f545a5c84a06a27f90f404252bab8fb7c5a105 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Thu, 26 Aug 2021 01:51:59 +0100 Subject: [PATCH] Enforce unsafe_op_in_unsafe_fn --- src/arch/x86_64.rs | 72 ++++++++++--------- src/find_fde/phdr.rs | 150 ++++++++++++++++++++------------------- src/find_fde/registry.rs | 86 ++++++++++++---------- src/lib.rs | 3 +- src/util.rs | 4 +- 5 files changed, 164 insertions(+), 151 deletions(-) diff --git a/src/arch/x86_64.rs b/src/arch/x86_64.rs index aa40053..9711cb3 100644 --- a/src/arch/x86_64.rs +++ b/src/arch/x86_64.rs @@ -19,7 +19,7 @@ impl Arch { } impl fmt::Debug for Context { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let mut fmt = fmt.debug_struct("Context"); for i in 0..=15 { fmt.field( @@ -91,43 +91,45 @@ pub extern "C-unwind" fn save_context() -> Context { #[naked] pub unsafe extern "C" fn restore_context(ctx: &Context) -> ! { - asm!( - " - /* Restore stack */ - mov rsp, [rdi + 0x38] + unsafe { + asm!( + " + /* Restore stack */ + mov rsp, [rdi + 0x38] - /* Restore callee-saved control registers */ - ldmxcsr [rdi + 0x88] - fldcw [rdi + 0x90] + /* Restore callee-saved control registers */ + ldmxcsr [rdi + 0x88] + fldcw [rdi + 0x90] - /* Restore return address */ - mov rax, [rdi + 0x80] - push rax + /* Restore return address */ + mov rax, [rdi + 0x80] + push rax - /* - * Restore general-purpose registers. Non-callee-saved registers are - * also restored because sometimes it's used to pass unwind arguments. - */ - mov rax, [rdi + 0x00] - mov rdx, [rdi + 0x08] - mov rcx, [rdi + 0x10] - mov rbx, [rdi + 0x18] - mov rsi, [rdi + 0x20] - mov rbp, [rdi + 0x30] - mov r8 , [rdi + 0x40] - mov r9 , [rdi + 0x48] - mov r10, [rdi + 0x50] - mov r11, [rdi + 0x58] - mov r12, [rdi + 0x60] - mov r13, [rdi + 0x68] - mov r14, [rdi + 0x70] - mov r15, [rdi + 0x78] + /* + * Restore general-purpose registers. Non-callee-saved registers are + * also restored because sometimes it's used to pass unwind arguments. + */ + mov rax, [rdi + 0x00] + mov rdx, [rdi + 0x08] + mov rcx, [rdi + 0x10] + mov rbx, [rdi + 0x18] + mov rsi, [rdi + 0x20] + mov rbp, [rdi + 0x30] + mov r8 , [rdi + 0x40] + mov r9 , [rdi + 0x48] + mov r10, [rdi + 0x50] + mov r11, [rdi + 0x58] + mov r12, [rdi + 0x60] + mov r13, [rdi + 0x68] + mov r14, [rdi + 0x70] + mov r15, [rdi + 0x78] - /* RDI resotred last */ - mov rdi, [rdi + 0x28] + /* RDI resotred last */ + mov rdi, [rdi + 0x28] - ret - ", - options(noreturn) - ); + ret + ", + options(noreturn) + ); + } } diff --git a/src/find_fde/phdr.rs b/src/find_fde/phdr.rs index deacd3a..9f541a2 100644 --- a/src/find_fde/phdr.rs +++ b/src/find_fde/phdr.rs @@ -29,84 +29,96 @@ unsafe extern "C" fn phdr_callback( _size: usize, data: *mut c_void, ) -> c_int { - let data = &mut *(data as *mut CallbackData); - let phdrs = slice::from_raw_parts((*info).dlpi_phdr, (*info).dlpi_phnum as usize); + unsafe { + let data = &mut *(data as *mut CallbackData); + let phdrs = slice::from_raw_parts((*info).dlpi_phdr, (*info).dlpi_phnum as usize); - let mut text = None; - let mut eh_frame_hdr = None; - let mut dynamic = None; + let mut text = None; + let mut eh_frame_hdr = None; + let mut dynamic = None; - for phdr in phdrs { - let start = (*info).dlpi_addr + phdr.p_vaddr; - match phdr.p_type { - PT_LOAD => { - let end = start + phdr.p_memsz; - let range = start..end; - if range.contains(&(data.pc as _)) { - text = Some(range); + for phdr in phdrs { + let start = (*info).dlpi_addr + phdr.p_vaddr; + match phdr.p_type { + PT_LOAD => { + let end = start + phdr.p_memsz; + let range = start..end; + if range.contains(&(data.pc as _)) { + text = Some(range); + } } + PT_GNU_EH_FRAME => { + eh_frame_hdr = Some(start); + } + PT_DYNAMIC => { + dynamic = Some(start); + } + _ => (), } - PT_GNU_EH_FRAME => { - eh_frame_hdr = Some(start); - } - PT_DYNAMIC => { - dynamic = Some(start); - } - _ => (), } - } - let text = match text { - Some(v) => v, - None => return 0, - }; + let text = match text { + Some(v) => v, + None => return 0, + }; - let eh_frame_hdr = match eh_frame_hdr { - Some(v) => v, - None => return 0, - }; + let eh_frame_hdr = match eh_frame_hdr { + Some(v) => v, + None => return 0, + }; - let mut bases = BaseAddresses::default() - .set_eh_frame_hdr(eh_frame_hdr as _) - .set_text(text.start as _); + let mut bases = BaseAddresses::default() + .set_eh_frame_hdr(eh_frame_hdr as _) + .set_text(text.start as _); - // Find the GOT section. - if let Some(start) = dynamic { - const DT_NULL: usize = 0; - const DT_PLTGOT: usize = 3; + // Find the GOT section. + if let Some(start) = dynamic { + const DT_NULL: usize = 0; + const DT_PLTGOT: usize = 3; - let mut tags = start as *const [usize; 2]; - let mut tag = *tags; - while tag[0] != DT_NULL { - if tag[0] == DT_PLTGOT { - bases = bases.set_got(tag[1] as _); - break; + let mut tags = start as *const [usize; 2]; + let mut tag = *tags; + while tag[0] != DT_NULL { + if tag[0] == DT_PLTGOT { + bases = bases.set_got(tag[1] as _); + break; + } + tags = tags.add(1); + tag = *tags; } - tags = tags.add(1); - tag = *tags; } - } - // Parse .eh_frame_hdr section. - let eh_frame_hdr = EhFrameHdr::new( - get_unlimited_slice(eh_frame_hdr as usize as _), - NativeEndian, - ) - .parse(&bases, mem::size_of::() as _); - let eh_frame_hdr = match eh_frame_hdr { - Ok(v) => v, - Err(_) => return 0, - }; + // Parse .eh_frame_hdr section. + let eh_frame_hdr = EhFrameHdr::new( + get_unlimited_slice(eh_frame_hdr as usize as _), + NativeEndian, + ) + .parse(&bases, mem::size_of::() as _); + let eh_frame_hdr = match eh_frame_hdr { + Ok(v) => v, + Err(_) => return 0, + }; - let eh_frame = deref_pointer(eh_frame_hdr.eh_frame_ptr()); - bases = bases.set_eh_frame(eh_frame as _); - let eh_frame = EhFrame::new(get_unlimited_slice(eh_frame as usize as _), NativeEndian); + let eh_frame = deref_pointer(eh_frame_hdr.eh_frame_ptr()); + bases = bases.set_eh_frame(eh_frame as _); + let eh_frame = EhFrame::new(get_unlimited_slice(eh_frame as usize as _), NativeEndian); - // Use binary search table for address if available. - if let Some(table) = eh_frame_hdr.table() { - if let Ok(fde) = - table.fde_for_address(&eh_frame, &bases, data.pc as _, EhFrame::cie_from_offset) - { + // Use binary search table for address if available. + if let Some(table) = eh_frame_hdr.table() { + if let Ok(fde) = + table.fde_for_address(&eh_frame, &bases, data.pc as _, EhFrame::cie_from_offset) + { + data.result = Some(FDESearchResult { + fde, + bases, + eh_frame, + }); + return 1; + } + } + + // Otherwise do the linear search. + if let Ok(fde) = eh_frame.fde_for_address(&bases, data.pc as _, EhFrame::cie_from_offset) { data.result = Some(FDESearchResult { fde, bases, @@ -114,17 +126,7 @@ unsafe extern "C" fn phdr_callback( }); return 1; } - } - // Otherwise do the linear search. - if let Ok(fde) = eh_frame.fde_for_address(&bases, data.pc as _, EhFrame::cie_from_offset) { - data.result = Some(FDESearchResult { - fde, - bases, - eh_frame, - }); - return 1; + 0 } - - 0 } diff --git a/src/find_fde/registry.rs b/src/find_fde/registry.rs index f63b026..376f948 100644 --- a/src/find_fde/registry.rs +++ b/src/find_fde/registry.rs @@ -41,9 +41,9 @@ pub fn get_finder() -> &'static Registry { impl super::FDEFinder for Registry { fn find_fde(&self, pc: usize) -> Option { let guard = get_finder().inner.lock().unwrap(); - let mut cur = guard.object; - unsafe { + let mut cur = guard.object; + while !cur.is_null() { let bases = BaseAddresses::default() .set_text((*cur).tbase as _) @@ -103,21 +103,23 @@ unsafe extern "C" fn __register_frame_info_bases( return; } - ob.write(Object { - next: core::ptr::null_mut(), - tbase: tbase as _, - dbase: dbase as _, - table: Table::Single(begin), - }); + unsafe { + ob.write(Object { + next: core::ptr::null_mut(), + tbase: tbase as _, + dbase: dbase as _, + table: Table::Single(begin), + }); - let mut guard = get_finder().inner.lock().unwrap(); - (*ob).next = guard.object; - guard.object = ob; + let mut guard = get_finder().inner.lock().unwrap(); + (*ob).next = guard.object; + guard.object = ob; + } } #[no_mangle] unsafe extern "C" fn __register_frame_info(begin: *const c_void, ob: *mut Object) { - __register_frame_info_bases(begin, ob, core::ptr::null_mut(), core::ptr::null_mut()); + unsafe { __register_frame_info_bases(begin, ob, core::ptr::null_mut(), core::ptr::null_mut()) } } #[no_mangle] @@ -127,7 +129,7 @@ unsafe extern "C" fn __register_frame(begin: *const c_void) { } let storage = Box::into_raw(Box::new(MaybeUninit::::uninit())) as *mut Object; - __register_frame_info(begin, storage); + unsafe { __register_frame_info(begin, storage) } } #[no_mangle] @@ -137,21 +139,25 @@ unsafe extern "C" fn __register_frame_info_table_bases( tbase: *const c_void, dbase: *const c_void, ) { - ob.write(Object { - next: core::ptr::null_mut(), - tbase: tbase as _, - dbase: dbase as _, - table: Table::Multiple(begin as _), - }); + unsafe { + ob.write(Object { + next: core::ptr::null_mut(), + tbase: tbase as _, + dbase: dbase as _, + table: Table::Multiple(begin as _), + }); - let mut guard = get_finder().inner.lock().unwrap(); - (*ob).next = guard.object; - guard.object = ob; + let mut guard = get_finder().inner.lock().unwrap(); + (*ob).next = guard.object; + guard.object = ob; + } } #[no_mangle] unsafe extern "C" fn __register_frame_info_table(begin: *const c_void, ob: *mut Object) { - __register_frame_info_table_bases(begin, ob, core::ptr::null_mut(), core::ptr::null_mut()); + unsafe { + __register_frame_info_table_bases(begin, ob, core::ptr::null_mut(), core::ptr::null_mut()) + } } #[no_mangle] @@ -161,37 +167,39 @@ unsafe extern "C" fn __register_frame_table(begin: *const c_void) { } let storage = Box::into_raw(Box::new(MaybeUninit::::uninit())) as *mut Object; - __register_frame_info_table(begin, storage); + unsafe { __register_frame_info_table(begin, storage) } } #[no_mangle] -unsafe extern "C" fn __deregister_frame_info_bases(begin: *const c_void) -> *mut Object { +extern "C" fn __deregister_frame_info_bases(begin: *const c_void) -> *mut Object { if begin.is_null() { return core::ptr::null_mut(); } let mut guard = get_finder().inner.lock().unwrap(); - let mut prev = &mut guard.object; - let mut cur = *prev; + unsafe { + let mut prev = &mut guard.object; + let mut cur = *prev; - while !cur.is_null() { - let found = match (*cur).table { - Table::Single(addr) => addr == begin, - _ => false, - }; - if found { - *prev = (*cur).next; - return cur; + while !cur.is_null() { + let found = match (*cur).table { + Table::Single(addr) => addr == begin, + _ => false, + }; + if found { + *prev = (*cur).next; + return cur; + } + prev = &mut (*cur).next; + cur = *prev; } - prev = &mut (*cur).next; - cur = *prev; } core::ptr::null_mut() } #[no_mangle] -unsafe extern "C" fn __deregister_frame_info(begin: *const c_void) -> *mut Object { +extern "C" fn __deregister_frame_info(begin: *const c_void) -> *mut Object { __deregister_frame_info_bases(begin) } @@ -201,5 +209,5 @@ unsafe extern "C" fn __deregister_frame(begin: *const c_void) { return; } let storage = __deregister_frame_info(begin); - drop(Box::from_raw(storage as *mut MaybeUninit)) + drop(unsafe { Box::from_raw(storage as *mut MaybeUninit) }) } diff --git a/src/lib.rs b/src/lib.rs index b4d4125..d04e2b1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,8 @@ #![feature(c_unwind)] #![feature(naked_functions)] #![feature(asm)] -#![allow(unused_unsafe)] +#![warn(rust_2018_idioms)] +#![warn(unsafe_op_in_unsafe_fn)] mod arch; mod find_fde; diff --git a/src/util.rs b/src/util.rs index 7e9687f..7277785 100644 --- a/src/util.rs +++ b/src/util.rs @@ -7,12 +7,12 @@ pub unsafe fn get_unlimited_slice<'a>(start: *const u8) -> &'a [u8] { let start = start as usize; let end = start.saturating_add(isize::MAX as _); let len = end - start; - core::slice::from_raw_parts(start as *const _, len) + unsafe { core::slice::from_raw_parts(start as *const _, len) } } pub unsafe fn deref_pointer(ptr: Pointer) -> usize { match ptr { Pointer::Direct(x) => x as _, - Pointer::Indirect(x) => *(x as *const _), + Pointer::Indirect(x) => unsafe { *(x as *const _) }, } }