Re: [PATCH v2 4/4] rust: add abstraction for `struct page`

From: Martin Rodriguez Reboredo
Date: Fri Feb 09 2024 - 23:23:58 EST


On 2/8/24 12:47, Alice Ryhl wrote:
[...]
+ /// Maps the page and reads from it into the given buffer.
+ ///
+ /// This method will perform bounds checks on the page offset. If `offset ..
+ /// offset+len` goes outside ot the page, then this call returns `EINVAL`.
+ ///
+ /// # Safety
+ ///
+ /// * Callers must ensure that `dst` is valid for writing `len` bytes.
+ /// * Callers must ensure that this call does not race with a write to the
+ /// same page that overlaps with this read.

This safety section says that a call mustn't race with a page that
overlaps this read, hmmmmm.

+ pub unsafe fn read_raw(&self, dst: *mut u8, offset: usize, len: usize) -> Result {
+ self.with_pointer_into_page(offset, len, move |src| {
+ // SAFETY: If `with_pointer_into_page` calls into this closure, then
+ // it has performed a bounds check and guarantees that `src` is
+ // valid for `len` bytes.
+ //
+ // There caller guarantees that there is no data race.
+ unsafe { ptr::copy(src, dst, len) };

If `src` and `dst` overlap then wouldn't that be a bad idea? If so then
how about mentioning that callers have to ensure that `dst` does not
overlap with the page that's being read and use
`core::ptr::copy_nonoverlapping` instead, otherwise the doc comment
could mention that `dst` can overlap.

+ Ok(())
+ })
+ }
+
+ /// Maps the page and writes into it from the given buffer.
+ ///
+ /// This method will perform bounds checks on the page offset. If `offset ..
+ /// offset+len` goes outside ot the page, then this call returns `EINVAL`.
+ ///
+ /// # Safety
+ ///
+ /// * Callers must ensure that `src` is valid for reading `len` bytes.
+ /// * Callers must ensure that this call does not race with a read or write
+ /// to the same page that overlaps with this write.
+ pub unsafe fn write_raw(&self, src: *const u8, offset: usize, len: usize) -> Result {
+ self.with_pointer_into_page(offset, len, move |dst| {
+ // SAFETY: If `with_pointer_into_page` calls into this closure, then
+ // it has performed a bounds check and guarantees that `dst` is
+ // valid for `len` bytes.
+ //
+ // There caller guarantees that there is no data race.
+ unsafe { ptr::copy(src, dst, len) };

Same as above

+ Ok(())
+ })
+ }
[...]