@@ -200,27 +200,44 @@ impl PageTable {
200
200
/// Clears all entries.
201
201
#[ inline]
202
202
pub fn zero ( & mut self ) {
203
- for entry in self . entries . iter_mut ( ) {
203
+ for entry in self . iter_mut ( ) {
204
204
entry. set_unused ( ) ;
205
205
}
206
206
}
207
207
208
208
/// Returns an iterator over the entries of the page table.
209
209
#[ inline]
210
210
pub fn iter ( & self ) -> impl Iterator < Item = & PageTableEntry > {
211
- self . entries . iter ( )
211
+ // Note that we intentionally don't just return `self.entries.iter()`:
212
+ // Some users may choose to create a reference to a page table at
213
+ // `0xffff_ffff_ffff_f000`. This causes problems because calculating
214
+ // the end pointer of the page tables causes an overflow. Therefore
215
+ // creating page tables at that address is unsound and must be avoided.
216
+ // Unfortunately creating such page tables is quite common when
217
+ // recursive page tables are used, so we try to avoid calculating the
218
+ // end pointer if possible. `core::slice::Iter` calculates the end
219
+ // pointer to determine when it should stop yielding elements. Because
220
+ // we want to avoid calculating the end pointer, we don't use
221
+ // `core::slice::Iter`, we implement our own iterator that doesn't
222
+ // calculate the end pointer. This doesn't make creating page tables at
223
+ // that address sound, but it avoids some easy to trigger
224
+ // miscompilations.
225
+ let ptr = self . entries . as_ptr ( ) ;
226
+ ( 0 ..512 ) . map ( move |i| unsafe { & * ptr. add ( i) } )
212
227
}
213
228
214
229
/// Returns an iterator that allows modifying the entries of the page table.
215
230
#[ inline]
216
231
pub fn iter_mut ( & mut self ) -> impl Iterator < Item = & mut PageTableEntry > {
217
- self . entries . iter_mut ( )
232
+ // See `Self::iter`.
233
+ let ptr = self . entries . as_mut_ptr ( ) ;
234
+ ( 0 ..512 ) . map ( move |i| unsafe { & mut * ptr. add ( i) } )
218
235
}
219
236
220
237
/// Checks if the page table is empty (all entries are zero).
221
238
#[ inline]
222
239
pub fn is_empty ( & self ) -> bool {
223
- self . entries . iter ( ) . all ( |entry| entry. is_unused ( ) )
240
+ self . iter ( ) . all ( |entry| entry. is_unused ( ) )
224
241
}
225
242
}
226
243
0 commit comments