Skip to content

Commit 312b382

Browse files
committed
feat(hal): use exposed provenance in vaddr<->ptr conversion (#509)
This changes the `VAddr` and `PAddr` types to use `ptr::expose_provenance` and `ptr::with_exposed_provenance` when converting to/from raw pointers. Hopefully, this will make things a little bit less UB. Fixes #366, more or less.
1 parent 1be23cb commit 312b382

File tree

6 files changed

+53
-12
lines changed

6 files changed

+53
-12
lines changed

hal-core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version = "0.1.0"
44
authors = ["Eliza Weisman <[email protected]>", "iximeow <[email protected]>"]
55
edition = "2021"
66
license = "MIT"
7-
rust-version = "1.81.0"
7+
rust-version = "1.84.0"
88

99
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1010

hal-core/src/addr.rs

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use core::{fmt, ops};
1+
use core::{fmt, ops, ptr};
22

33
pub trait Address:
44
Copy
@@ -117,19 +117,40 @@ pub trait Address:
117117
self.is_aligned(core::mem::align_of::<T>())
118118
}
119119

120+
/// Converts this address into a const pointer to a value of type `T`.
121+
///
122+
/// # Panics
123+
///
124+
/// - If `self` is not aligned for a `T`-typed value.
125+
#[inline]
126+
#[track_caller]
127+
fn as_ptr<T>(self) -> *const T {
128+
// Some architectures permit unaligned reads, but Rust considers
129+
// dereferencing a pointer that isn't type-aligned to be UB.
130+
assert!(
131+
self.is_aligned_for::<T>(),
132+
"assertion failed: self.is_aligned_for::<{}>();\n\tself={self:?}",
133+
core::any::type_name::<T>(),
134+
);
135+
ptr::with_exposed_provenance(self.as_usize())
136+
}
137+
138+
/// Converts this address into a mutable pointer to a value of type `T`.
139+
///
120140
/// # Panics
121141
///
122142
/// - If `self` is not aligned for a `T`-typed value.
143+
#[inline]
123144
#[track_caller]
124-
fn as_ptr<T>(self) -> *mut T {
145+
fn as_mut_ptr<T>(self) -> *mut T {
125146
// Some architectures permit unaligned reads, but Rust considers
126147
// dereferencing a pointer that isn't type-aligned to be UB.
127148
assert!(
128149
self.is_aligned_for::<T>(),
129150
"assertion failed: self.is_aligned_for::<{}>();\n\tself={self:?}",
130151
core::any::type_name::<T>(),
131152
);
132-
self.as_usize() as *mut T
153+
ptr::with_exposed_provenance_mut(self.as_usize())
133154
}
134155
}
135156

@@ -327,13 +348,27 @@ macro_rules! impl_addrs {
327348
Address::is_aligned_for::<T>(self)
328349
}
329350

351+
/// Converts this address into a const pointer to a value of type `T`.
352+
///
330353
/// # Panics
331354
///
332355
/// - If `self` is not aligned for a `T`-typed value.
333356
#[inline]
334-
pub fn as_ptr<T>(self) -> *mut T {
357+
#[track_caller]
358+
pub fn as_ptr<T>(self) -> *const T {
335359
Address::as_ptr(self)
336360
}
361+
362+
/// Converts this address into a mutable pointer to a value of type `T`.
363+
///
364+
/// # Panics
365+
///
366+
/// - If `self` is not aligned for a `T`-typed value.
367+
#[inline]
368+
#[track_caller]
369+
pub fn as_mut_ptr<T>(self) -> *mut T {
370+
Address::as_mut_ptr(self)
371+
}
337372
}
338373
)+
339374
}
@@ -392,9 +427,15 @@ impl VAddr {
392427
Self(u)
393428
}
394429

430+
/// Constructs a `VAddr` from a `*const T` pointer, exposing its provenance.
431+
#[inline]
432+
pub fn from_ptr<T: ?Sized>(ptr: *const T) -> Self {
433+
Self::from_usize(ptr.expose_provenance())
434+
}
435+
395436
#[inline]
396437
pub fn of<T: ?Sized>(pointee: &T) -> Self {
397-
Self::from_usize(pointee as *const _ as *const () as usize)
438+
Self::from_ptr(pointee as *const T)
398439
}
399440
}
400441

hal-core/src/mem/page.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ impl<A: Address, S: Size> Page<A, S> {
484484
/// When calling this method, ensure that the page will not be mutated
485485
/// concurrently, including by user code.
486486
pub unsafe fn as_slice(&self) -> &[u8] {
487-
let start = self.base.as_ptr() as *const u8;
487+
let start = self.base.as_mut_ptr() as *const u8;
488488
slice::from_raw_parts::<u8>(start, self.size.as_usize())
489489
}
490490

@@ -495,7 +495,7 @@ impl<A: Address, S: Size> Page<A, S> {
495495
/// When calling this method, ensure that the page will not be read or mutated
496496
/// concurrently, including by user code.
497497
pub unsafe fn as_slice_mut(&mut self) -> &mut [u8] {
498-
let start = self.base.as_ptr::<u8>() as *mut _;
498+
let start = self.base.as_mut_ptr::<u8>() as *mut _;
499499
slice::from_raw_parts_mut::<u8>(start, self.size.as_usize())
500500
}
501501
}

hal-x86_64/src/interrupt/apic/ioapic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ impl IoApic {
348348
tracing::debug!("mapped I/O APIC MMIO page!");
349349
}
350350

351-
let registers = unsafe { Volatile::new(&mut *base.as_ptr::<MmioRegisters>()) };
351+
let registers = unsafe { Volatile::new(&mut *base.as_mut_ptr::<MmioRegisters>()) };
352352
let mut ioapic = Self { registers };
353353
tracing::info!(
354354
addr = ?base,

hal-x86_64/src/interrupt/apic/local.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ impl LocalApic {
395395
addr.is_aligned(16usize),
396396
"Local APIC memory-mapped registers must be 16-byte aligned!"
397397
);
398-
let reference = &mut *addr.as_ptr::<T>();
398+
let reference = &mut *addr.as_mut_ptr::<T>();
399399
LocalApicRegister::<T, A>::volatile(reference)
400400
}
401401
}

hal-x86_64/src/mm.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ impl<R: level::Recursive> PageTable<R> {
303303
tracing::trace!(next.addr = ?vaddr, "found next table virtual address");
304304
// XXX(eliza): this _probably_ could be be a `new_unchecked`...if, after
305305
// all this, the next table address is null...we're probably pretty fucked!
306-
Some(unsafe { &*NonNull::new(vaddr.as_ptr())?.as_ptr() })
306+
Some(unsafe { &*NonNull::new(vaddr.as_mut_ptr())?.as_ptr() })
307307
}
308308

309309
#[inline]
@@ -893,7 +893,7 @@ mycotest::decl_test! {
893893
};
894894
tracing::info!(?page, "page mapped!");
895895

896-
let page_ptr = page.base_addr().as_ptr::<u64>();
896+
let page_ptr = page.base_addr().as_mut_ptr::<u64>();
897897
unsafe { page_ptr.offset(400).write_volatile(0x_f021_f077_f065_f04e)};
898898

899899
tracing::info!("wow, it didn't fault");

0 commit comments

Comments
 (0)