Skip to content

Commit 3de642b

Browse files
committed
add work-around for bad page table references
1 parent 486c2a4 commit 3de642b

File tree

1 file changed

+21
-4
lines changed

1 file changed

+21
-4
lines changed

src/structures/paging/page_table.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)