瀏覽代碼

Enforce unsafe_op_in_unsafe_fn

Gary Guo 3 年之前
父節點
當前提交
28f545a5c8
共有 5 個文件被更改,包括 179 次插入166 次删除
  1. 42 40
      src/arch/x86_64.rs
  2. 83 81
      src/find_fde/phdr.rs
  3. 50 42
      src/find_fde/registry.rs
  4. 2 1
      src/lib.rs
  5. 2 2
      src/util.rs

+ 42 - 40
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]
-
-        /* Restore callee-saved control registers */
-        ldmxcsr [rdi + 0x88]
-        fldcw [rdi + 0x90]
-
-        /* 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]
-
-        /* RDI resotred last */
-        mov rdi, [rdi + 0x28]
-
-        ret
-        ",
-        options(noreturn)
-    );
+    unsafe {
+        asm!(
+            "
+            /* Restore stack */
+            mov rsp, [rdi + 0x38]
+
+            /* Restore callee-saved control registers */
+            ldmxcsr [rdi + 0x88]
+            fldcw [rdi + 0x90]
+
+            /* 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]
+
+            /* RDI resotred last */
+            mov rdi, [rdi + 0x28]
+
+            ret
+            ",
+            options(noreturn)
+        );
+    }
 }

+ 83 - 81
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);
-
-    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);
+    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;
+
+        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 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 _);
+
+        // 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;
+                }
+                tags = tags.add(1);
+                tag = *tags;
             }
-            _ => (),
         }
-    }
 
-    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 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;
-
-        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;
+        // 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::<usize>() 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);
+
+        // 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;
             }
-            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::<usize>() 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);
-
-    // 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)
-        {
+        // 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
 }

+ 50 - 42
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<FDESearchResult> {
         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),
-    });
-
-    let mut guard = get_finder().inner.lock().unwrap();
-    (*ob).next = guard.object;
-    guard.object = ob;
+    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;
+    }
 }
 
 #[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::<Object>::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 _),
-    });
-
-    let mut guard = get_finder().inner.lock().unwrap();
-    (*ob).next = guard.object;
-    guard.object = ob;
+    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;
+    }
 }
 
 #[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::<Object>::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;
-
-    while !cur.is_null() {
-        let found = match (*cur).table {
-            Table::Single(addr) => addr == begin,
-            _ => false,
-        };
-        if found {
-            *prev = (*cur).next;
-            return cur;
+    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;
+            }
+            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<Object>))
+    drop(unsafe { Box::from_raw(storage as *mut MaybeUninit<Object>) })
 }

+ 2 - 1
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;

+ 2 - 2
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 _) },
     }
 }