@@ -82,7 +82,7 @@ impl<const ORDER: u32> Pages<ORDER> {
82
82
///
83
83
/// # Safety
84
84
///
85
- /// Callers must ensure that the destination buffer is valid for the given length.
85
+ /// Callers must ensure that the destination buffer is valid for writes for the given length.
86
86
/// Additionally, if the raw buffer is intended to be recast, they must ensure that the data
87
87
/// can be safely cast; [`crate::io_buffer::ReadableFromBytes`] has more details about it.
88
88
pub unsafe fn read ( & self , dest : * mut u8 , offset : usize , len : usize ) -> Result {
@@ -93,15 +93,23 @@ impl<const ORDER: u32> Pages<ORDER> {
93
93
}
94
94
95
95
let mapping = self . kmap ( 0 ) . ok_or ( Error :: EINVAL ) ?;
96
- unsafe { ptr:: copy ( ( mapping. ptr as * mut u8 ) . add ( offset) , dest, len) } ;
96
+ // SAFETY: we just checked that `offset + len <= PAGE_SIZE`, so `mapping.ptr` and
97
+ // `mapping.ptr + offset` are in the same allocated object, the page we're
98
+ // reading from, with no overflow. Also, `offset <= PAGE_LEN < isize::MAX`
99
+ // so `offset` can't overflow an `isize`.
100
+ let src = unsafe { ( mapping. ptr as * mut u8 ) . add ( offset) } ;
101
+ // SAFETY: `src` is valid for reads from the type invariants, and `dest` is
102
+ // guaranteed by the caller to be valid for writes. Because we're copying `u8`s
103
+ // which have an alignment of 1, `src` and `dest` are always properly aligned.
104
+ unsafe { ptr:: copy ( src, dest, len) } ;
97
105
Ok ( ( ) )
98
106
}
99
107
100
108
/// Maps the pages and writes into them from the given bufer.
101
109
///
102
110
/// # Safety
103
111
///
104
- /// Callers must ensure that the buffer is valid for the given length. Additionally, if the
112
+ /// Callers must ensure that the source buffer is valid for reads for the given length. Additionally, if the
105
113
/// page is (or will be) mapped by userspace, they must ensure that no kernel data is leaked
106
114
/// through padding if it was cast from another type; [`crate::io_buffer::WritableToBytes`] has
107
115
/// more details about it.
@@ -113,7 +121,15 @@ impl<const ORDER: u32> Pages<ORDER> {
113
121
}
114
122
115
123
let mapping = self . kmap ( 0 ) . ok_or ( Error :: EINVAL ) ?;
116
- unsafe { ptr:: copy ( src, ( mapping. ptr as * mut u8 ) . add ( offset) , len) } ;
124
+ // SAFETY: we just checked that `offset + len <= PAGE_SIZE`, so `mapping.ptr` and
125
+ // `mapping.ptr + offset` are in the same allocated object, the page we're
126
+ // reading from, with no overflow. Also, `offset <= PAGE_LEN < isize::MAX`
127
+ // so `offset` can't overflow an `isize`.
128
+ let dest = unsafe { ( mapping. ptr as * mut u8 ) . add ( offset) } ;
129
+ // SAFETY: `src` is guaranteed by the caller to be valid for reads, and `dest` is
130
+ //valid for writes from the type invariants. Because we're copying `u8`s
131
+ // which have an alignment of 1, `src` and `dest` are always properly aligned.
132
+ unsafe { ptr:: copy ( src, dest, len) } ;
117
133
Ok ( ( ) )
118
134
}
119
135
0 commit comments