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