Skip to content

Commit c46b513

Browse files
committed
Remove some unsafe code; fix a soundness hole
Replace a number of lines of unsafe code with safe equivalents, some using `zerocopy`. In one instance, fix a soundness hole (#720). Closes #720
1 parent b65ab93 commit c46b513

File tree

9 files changed

+71
-32
lines changed

9 files changed

+71
-32
lines changed

Cargo.lock

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ exclude = [
2828
[dependencies]
2929
cfg-if = "1.0"
3030
rustc-demangle = "0.1.24"
31+
zerocopy = { version = "0.8.26", features = ["derive"] }
3132

3233
# Optionally enable the ability to serialize a `Backtrace`, controlled through
3334
# the `serialize-serde` feature below.

crates/as-if-std/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ bench = false
1515
cfg-if = "1.0"
1616
rustc-demangle = "0.1.21"
1717
libc = { version = "0.2.156", default-features = false }
18+
zerocopy = { version = "0.8.26", features = ["derive"] }
1819

1920
[target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies]
2021
miniz_oxide = { version = "0.8", optional = true, default-features = false }

src/backtrace/win32.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ use super::super::{dbghelp, windows_sys::*};
1313
use core::ffi::c_void;
1414
use core::mem;
1515

16+
use zerocopy::{FromBytes, FromZeros};
17+
1618
#[derive(Clone, Copy)]
1719
pub enum StackFrame {
1820
New(STACKFRAME_EX),
@@ -92,6 +94,7 @@ impl Frame {
9294
}
9395

9496
#[repr(C, align(16))] // required by `CONTEXT`, is a FIXME in windows metadata right now
97+
#[derive(FromBytes)]
9598
struct MyContext(CONTEXT);
9699

97100
#[inline(always)]
@@ -100,7 +103,7 @@ pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool) {
100103
let process = GetCurrentProcess();
101104
let thread = GetCurrentThread();
102105

103-
let mut context = mem::zeroed::<MyContext>();
106+
let mut context = MyContext::new_zeroed();
104107
RtlCaptureContext(&mut context.0);
105108

106109
// Ensure this process's symbols are initialized

src/backtrace/win64.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
99
use super::super::windows_sys::*;
1010
use core::ffi::c_void;
11+
use zerocopy::{FromBytes, FromZeros};
1112

1213
#[derive(Clone, Copy)]
1314
pub struct Frame {
@@ -46,6 +47,7 @@ impl Frame {
4647
}
4748
}
4849

50+
#[derive(FromBytes)]
4951
#[repr(C, align(16))] // required by `CONTEXT`, is a FIXME in windows metadata right now
5052
struct MyContext(CONTEXT);
5153

@@ -80,8 +82,7 @@ pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool) {
8082
use core::ptr;
8183

8284
// Capture the initial context to start walking from.
83-
// FIXME: shouldn't this have a Default impl?
84-
let mut context = unsafe { core::mem::zeroed::<MyContext>() };
85+
let mut context = MyContext::new_zeroed();
8586
unsafe { RtlCaptureContext(&mut context.0) };
8687

8788
loop {

src/print/fuchsia.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use core::fmt::{self, Write};
2-
use core::mem::{size_of, transmute};
2+
use core::mem::size_of;
33
use core::slice::from_raw_parts;
44
use libc::c_char;
5+
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
56

67
unsafe extern "C" {
78
// dl_iterate_phdr takes a callback that will receive a dl_phdr_info pointer
@@ -119,6 +120,7 @@ const NT_GNU_BUILD_ID: u32 = 3;
119120
// Elf_Nhdr represents an ELF note header in the endianness of the target.
120121
#[allow(non_camel_case_types)]
121122
#[repr(C)]
123+
#[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
122124
struct Elf_Nhdr {
123125
n_namesz: u32,
124126
n_descsz: u32,
@@ -181,15 +183,9 @@ fn take_bytes_align4<'a>(num: usize, bytes: &mut &'a [u8]) -> Option<&'a [u8]> {
181183
// architectures correctness). The values in the Elf_Nhdr fields might
182184
// be nonsense but this function ensures no such thing.
183185
fn take_nhdr<'a>(bytes: &mut &'a [u8]) -> Option<&'a Elf_Nhdr> {
184-
if size_of::<Elf_Nhdr>() > bytes.len() {
185-
return None;
186-
}
187-
// This is safe as long as there is enough space and we just confirmed that
188-
// in the if statement above so this should not be unsafe.
189-
let out = unsafe { transmute::<*const u8, &'a Elf_Nhdr>(bytes.as_ptr()) };
190-
// Note that sice_of::<Elf_Nhdr>() is always 4-byte aligned.
191-
*bytes = &bytes[size_of::<Elf_Nhdr>()..];
192-
Some(out)
186+
let (hdr, suffix) = Elf_Nhdr::ref_from_prefix(*bytes).ok()?;
187+
*bytes = suffix;
188+
Some(hdr)
193189
}
194190

195191
impl<'a> Iterator for NoteIter<'a> {

src/symbolize/dbghelp.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,20 @@ unsafe fn do_resolve(
222222
get_line_from_addr: impl FnOnce(&mut IMAGEHLP_LINEW64) -> BOOL,
223223
cb: &mut dyn FnMut(&super::Symbol),
224224
) {
225-
const SIZE: usize = 2 * MAX_SYM_NAME as usize + mem::size_of::<SYMBOL_INFOW>();
226-
let mut data = Aligned8([0u8; SIZE]);
227-
let info = unsafe { &mut *data.0.as_mut_ptr().cast::<SYMBOL_INFOW>() };
225+
const TRAILER_SIZE: usize = 2 * MAX_SYM_NAME as usize;
226+
227+
#[repr(C)]
228+
#[derive(zerocopy::IntoBytes)]
229+
struct Data {
230+
symbol_infow: SYMBOL_INFOW,
231+
__max_sym_name: [u8; TRAILER_SIZE],
232+
}
233+
234+
let mut data = Aligned8(Data {
235+
symbol_infow: zerocopy::transmute!([0u8; size_of::<SYMBOL_INFOW>()]),
236+
__max_sym_name: [0u8; TRAILER_SIZE],
237+
});
238+
let info = &mut data.0.symbol_infow;
228239
info.MaxNameLen = MAX_SYM_NAME as u32;
229240
// the struct size in C. the value is different to
230241
// `size_of::<SYMBOL_INFOW>() - MAX_SYM_NAME + 1` (== 81)

src/symbolize/gimli/libs_illumos.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use super::{Library, LibrarySegment};
44
use alloc::borrow::ToOwned;
55
use alloc::vec::Vec;
66
use core::ffi::CStr;
7-
use core::mem;
87
use object::NativeEndian;
98

109
#[cfg(target_pointer_width = "64")]
@@ -38,8 +37,8 @@ pub(super) fn native_libraries() -> Vec<Library> {
3837
let mut libs = Vec::new();
3938

4039
// Request the current link map from the runtime linker:
40+
let mut map: *const LinkMap = core::ptr::null();
4141
let map = unsafe {
42-
let mut map: *const LinkMap = mem::zeroed();
4342
if dlinfo(
4443
RTLD_SELF,
4544
RTLD_DI_LINKMAP,

src/windows_sys.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
dead_code,
88
clippy::all
99
)]
10+
11+
use zerocopy::{FromBytes, Immutable, IntoBytes};
12+
1013
windows_targets::link!("dbghelp.dll" "system" fn EnumerateLoadedModulesW64(hprocess : HANDLE, enumloadedmodulescallback : PENUMLOADED_MODULES_CALLBACKW64, usercontext : *const core::ffi::c_void) -> BOOL);
1114
windows_targets::link!("dbghelp.dll" "system" fn StackWalk64(machinetype : u32, hprocess : HANDLE, hthread : HANDLE, stackframe : *mut STACKFRAME64, contextrecord : *mut core::ffi::c_void, readmemoryroutine : PREAD_PROCESS_MEMORY_ROUTINE64, functiontableaccessroutine : PFUNCTION_TABLE_ACCESS_ROUTINE64, getmodulebaseroutine : PGET_MODULE_BASE_ROUTINE64, translateaddress : PTRANSLATE_ADDRESS_ROUTINE64) -> BOOL);
1215
windows_targets::link!("dbghelp.dll" "system" fn StackWalkEx(machinetype : u32, hprocess : HANDLE, hthread : HANDLE, stackframe : *mut STACKFRAME_EX, contextrecord : *mut core::ffi::c_void, readmemoryroutine : PREAD_PROCESS_MEMORY_ROUTINE64, functiontableaccessroutine : PFUNCTION_TABLE_ACCESS_ROUTINE64, getmodulebaseroutine : PGET_MODULE_BASE_ROUTINE64, translateaddress : PTRANSLATE_ADDRESS_ROUTINE64, flags : u32) -> BOOL);
@@ -58,7 +61,7 @@ pub struct ADDRESS64 {
5861
}
5962
pub type ADDRESS_MODE = i32;
6063
#[repr(C)]
61-
#[derive(Clone, Copy)]
64+
#[derive(Clone, Copy, FromBytes, Immutable)]
6265
pub union ARM64_NT_NEON128 {
6366
pub Anonymous: ARM64_NT_NEON128_0,
6467
pub D: [f64; 2],
@@ -67,7 +70,7 @@ pub union ARM64_NT_NEON128 {
6770
pub B: [u8; 16],
6871
}
6972
#[repr(C)]
70-
#[derive(Clone, Copy)]
73+
#[derive(Clone, Copy, FromBytes, Immutable)]
7174
pub struct ARM64_NT_NEON128_0 {
7275
pub Low: u64,
7376
pub High: i64,
@@ -76,7 +79,7 @@ pub const AddrModeFlat: ADDRESS_MODE = 3i32;
7679
pub type BOOL = i32;
7780
#[repr(C)]
7881
#[cfg(target_arch = "aarch64")]
79-
#[derive(Clone, Copy)]
82+
#[derive(Clone, Copy, FromBytes)]
8083
pub struct CONTEXT {
8184
pub ContextFlags: CONTEXT_FLAGS,
8285
pub Cpsr: u32,
@@ -93,14 +96,14 @@ pub struct CONTEXT {
9396
}
9497
#[repr(C)]
9598
#[cfg(target_arch = "aarch64")]
96-
#[derive(Clone, Copy)]
99+
#[derive(Clone, Copy, FromBytes, Immutable)]
97100
pub union CONTEXT_0 {
98101
pub Anonymous: CONTEXT_0_0,
99102
pub X: [u64; 31],
100103
}
101104
#[repr(C)]
102105
#[cfg(target_arch = "aarch64")]
103-
#[derive(Clone, Copy)]
106+
#[derive(Clone, Copy, FromBytes, Immutable)]
104107
pub struct CONTEXT_0_0 {
105108
pub X0: u64,
106109
pub X1: u64,
@@ -136,7 +139,7 @@ pub struct CONTEXT_0_0 {
136139
}
137140
#[repr(C)]
138141
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
139-
#[derive(Clone, Copy)]
142+
#[derive(Clone, Copy, FromBytes)]
140143
pub struct CONTEXT {
141144
pub P1Home: u64,
142145
pub P2Home: u64,
@@ -187,14 +190,14 @@ pub struct CONTEXT {
187190
}
188191
#[repr(C)]
189192
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
190-
#[derive(Clone, Copy)]
193+
#[derive(Clone, Copy, FromBytes, Immutable)]
191194
pub union CONTEXT_0 {
192195
pub FltSave: XSAVE_FORMAT,
193196
pub Anonymous: CONTEXT_0_0,
194197
}
195198
#[repr(C)]
196199
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
197-
#[derive(Clone, Copy)]
200+
#[derive(Clone, Copy, FromBytes, Immutable)]
198201
pub struct CONTEXT_0_0 {
199202
pub Header: [M128A; 2],
200203
pub Legacy: [M128A; 8],
@@ -217,7 +220,7 @@ pub struct CONTEXT_0_0 {
217220
}
218221
#[repr(C)]
219222
#[cfg(target_arch = "x86")]
220-
#[derive(Clone, Copy)]
223+
#[derive(Clone, Copy, FromBytes)]
221224
pub struct CONTEXT {
222225
pub ContextFlags: CONTEXT_FLAGS,
223226
pub Dr0: u32,
@@ -292,7 +295,7 @@ pub struct FLOATING_SAVE_AREA {
292295
}
293296
#[repr(C)]
294297
#[cfg(target_arch = "x86")]
295-
#[derive(Clone, Copy)]
298+
#[derive(Clone, Copy, FromBytes)]
296299
pub struct FLOATING_SAVE_AREA {
297300
pub ControlWord: u32,
298301
pub StatusWord: u32,
@@ -466,7 +469,7 @@ pub struct KNONVOLATILE_CONTEXT_POINTERS {
466469
pub Dummy: u32,
467470
}
468471
#[repr(C)]
469-
#[derive(Clone, Copy)]
472+
#[derive(Clone, Copy, FromBytes, Immutable)]
470473
pub struct M128A {
471474
pub Low: u64,
472475
pub High: i64,
@@ -563,7 +566,7 @@ pub struct STACKFRAME_EX {
563566
pub InlineFrameContext: u32,
564567
}
565568
#[repr(C)]
566-
#[derive(Clone, Copy)]
569+
#[derive(Clone, Copy, FromBytes, IntoBytes)]
567570
pub struct SYMBOL_INFOW {
568571
pub SizeOfStruct: u32,
569572
pub TypeIndex: u32,
@@ -572,6 +575,7 @@ pub struct SYMBOL_INFOW {
572575
pub Size: u32,
573576
pub ModBase: u64,
574577
pub Flags: SYMBOL_INFO_FLAGS,
578+
__padding0: [u8; 4],
575579
pub Value: u64,
576580
pub Address: u64,
577581
pub Register: u32,
@@ -580,6 +584,7 @@ pub struct SYMBOL_INFOW {
580584
pub NameLen: u32,
581585
pub MaxNameLen: u32,
582586
pub Name: [u16; 1],
587+
__padding1: [u8; 2],
583588
}
584589
pub type SYMBOL_INFO_FLAGS = u32;
585590
pub const SYMOPT_DEFERRED_LOADS: u32 = 4u32;
@@ -623,7 +628,7 @@ pub type WAIT_EVENT = u32;
623628
target_arch = "arm64ec",
624629
target_arch = "x86_64"
625630
))]
626-
#[derive(Clone, Copy)]
631+
#[derive(Clone, Copy, FromBytes, Immutable)]
627632
pub struct XSAVE_FORMAT {
628633
pub ControlWord: u16,
629634
pub StatusWord: u16,
@@ -644,7 +649,7 @@ pub struct XSAVE_FORMAT {
644649
}
645650
#[repr(C)]
646651
#[cfg(target_arch = "x86")]
647-
#[derive(Clone, Copy)]
652+
#[derive(Clone, Copy, FromBytes, Immutable)]
648653
pub struct XSAVE_FORMAT {
649654
pub ControlWord: u16,
650655
pub StatusWord: u16,

0 commit comments

Comments
 (0)