@@ -200,27 +200,44 @@ impl PageTable {
200200 /// Clears all entries.
201201 #[ inline]
202202 pub fn zero ( & mut self ) {
203- for entry in self . entries . iter_mut ( ) {
203+ for entry in self . iter_mut ( ) {
204204 entry. set_unused ( ) ;
205205 }
206206 }
207207
208208 /// Returns an iterator over the entries of the page table.
209209 #[ inline]
210210 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) } )
212227 }
213228
214229 /// Returns an iterator that allows modifying the entries of the page table.
215230 #[ inline]
216231 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) } )
218235 }
219236
220237 /// Checks if the page table is empty (all entries are zero).
221238 #[ inline]
222239 pub fn is_empty ( & self ) -> bool {
223- self . entries . iter ( ) . all ( |entry| entry. is_unused ( ) )
240+ self . iter ( ) . all ( |entry| entry. is_unused ( ) )
224241 }
225242}
226243
0 commit comments