@@ -209,27 +209,42 @@ impl PageTable {
209209 /// Clears all entries.
210210 #[ inline]
211211 pub fn zero ( & mut self ) {
212- for entry in self . entries . iter_mut ( ) {
212+ for entry in self . iter_mut ( ) {
213213 entry. set_unused ( ) ;
214214 }
215215 }
216216
217217 /// Returns an iterator over the entries of the page table.
218218 #[ inline]
219219 pub fn iter ( & self ) -> impl Iterator < Item = & PageTableEntry > {
220- self . entries . iter ( )
220+ ( 0 .. 512 ) . map ( move |i| & self . entries [ i ] )
221221 }
222222
223223 /// Returns an iterator that allows modifying the entries of the page table.
224224 #[ inline]
225225 pub fn iter_mut ( & mut self ) -> impl Iterator < Item = & mut PageTableEntry > {
226- self . entries . iter_mut ( )
226+ // Note that we intentionally don't just return `self.entries.iter()`:
227+ // Some users may choose to create a reference to a page table at
228+ // `0xffff_ffff_ffff_f000`. This causes problems because calculating
229+ // the end pointer of the page tables causes an overflow. Therefore
230+ // creating page tables at that address is unsound and must be avoided.
231+ // Unfortunately creating such page tables is quite common when
232+ // recursive page tables are used, so we try to avoid calculating the
233+ // end pointer if possible. `core::slice::Iter` calculates the end
234+ // pointer to determine when it should stop yielding elements. Because
235+ // we want to avoid calculating the end pointer, we don't use
236+ // `core::slice::Iter`, we implement our own iterator that doesn't
237+ // calculate the end pointer. This doesn't make creating page tables at
238+ // that address sound, but it avoids some easy to trigger
239+ // miscompilations.
240+ let ptr = self . entries . as_mut_ptr ( ) ;
241+ ( 0 ..512 ) . map ( move |i| unsafe { & mut * ptr. add ( i) } )
227242 }
228243
229244 /// Checks if the page table is empty (all entries are zero).
230245 #[ inline]
231246 pub fn is_empty ( & self ) -> bool {
232- self . entries . iter ( ) . all ( |entry| entry. is_unused ( ) )
247+ self . iter ( ) . all ( |entry| entry. is_unused ( ) )
233248 }
234249}
235250
0 commit comments