Skip to content

Commit

Permalink
Merge pull request #425 from Freax13/fix/overflow
Browse files Browse the repository at this point in the history
add workaround for recursive page tables with recursive index 511
  • Loading branch information
Freax13 committed Jun 19, 2023
2 parents f49761b + 1e66b26 commit 9e0a8d1
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 4 deletions.
8 changes: 8 additions & 0 deletions src/structures/paging/mapper/recursive_page_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ impl<'a> RecursivePageTable<'a> {
/// - The page table must be active, i.e. the CR3 register must contain its physical address.
///
/// Otherwise `Err(())` is returned.
///
/// ## Safety
///
/// Note that creating a `PageTable` with recursive index 511 is unsound
/// because allocating the last byte of the address space can lead to pointer
/// overflows and undefined behavior. For more details, see the discussions
/// [on Zulip](https://rust-lang.zulipchat.com/#narrow/stream/136281-t-opsem/topic/end-of-address-space)
/// and [in the `unsafe-code-guidelines ` repo]https://github.com/rust-lang/unsafe-code-guidelines/issues/420).

Check warning on line 57 in src/structures/paging/mapper/recursive_page_table.rs

View workflow job for this annotation

GitHub Actions / Test MSRV and Stable Features (nightly)

this URL is not a hyperlink

Check warning on line 57 in src/structures/paging/mapper/recursive_page_table.rs

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

this URL is not a hyperlink

Check warning on line 57 in src/structures/paging/mapper/recursive_page_table.rs

View workflow job for this annotation

GitHub Actions / Test (macos-latest)

this URL is not a hyperlink

Check warning on line 57 in src/structures/paging/mapper/recursive_page_table.rs

View workflow job for this annotation

GitHub Actions / Test (windows-latest)

this URL is not a hyperlink

Check warning on line 57 in src/structures/paging/mapper/recursive_page_table.rs

View workflow job for this annotation

GitHub Actions / Test MSRV and Stable Features (1.59)

this URL is not a hyperlink

Check warning on line 57 in src/structures/paging/mapper/recursive_page_table.rs

View workflow job for this annotation

GitHub Actions / Test MSRV and Stable Features (nightly)

this URL is not a hyperlink

Check warning on line 57 in src/structures/paging/mapper/recursive_page_table.rs

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

this URL is not a hyperlink

Check warning on line 57 in src/structures/paging/mapper/recursive_page_table.rs

View workflow job for this annotation

GitHub Actions / Test (macos-latest)

this URL is not a hyperlink

Check warning on line 57 in src/structures/paging/mapper/recursive_page_table.rs

View workflow job for this annotation

GitHub Actions / Test (windows-latest)

this URL is not a hyperlink

Check warning on line 57 in src/structures/paging/mapper/recursive_page_table.rs

View workflow job for this annotation

GitHub Actions / Test MSRV and Stable Features (1.59)

this URL is not a hyperlink

Check warning on line 57 in src/structures/paging/mapper/recursive_page_table.rs

View workflow job for this annotation

GitHub Actions / Test MSRV and Stable Features (nightly)

this URL is not a hyperlink

Check warning on line 57 in src/structures/paging/mapper/recursive_page_table.rs

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

this URL is not a hyperlink

Check warning on line 57 in src/structures/paging/mapper/recursive_page_table.rs

View workflow job for this annotation

GitHub Actions / Test (macos-latest)

this URL is not a hyperlink

Check warning on line 57 in src/structures/paging/mapper/recursive_page_table.rs

View workflow job for this annotation

GitHub Actions / Test MSRV and Stable Features (1.59)

this URL is not a hyperlink

Check warning on line 57 in src/structures/paging/mapper/recursive_page_table.rs

View workflow job for this annotation

GitHub Actions / Test (windows-latest)

this URL is not a hyperlink
#[inline]
pub fn new(table: &'a mut PageTable) -> Result<Self, InvalidPageTable> {
let page = Page::containing_address(VirtAddr::new(table as *const _ as u64));
Expand Down
23 changes: 19 additions & 4 deletions src/structures/paging/page_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,27 +209,42 @@ impl PageTable {
/// Clears all entries.
#[inline]
pub fn zero(&mut self) {
for entry in self.entries.iter_mut() {
for entry in self.iter_mut() {
entry.set_unused();
}
}

/// Returns an iterator over the entries of the page table.
#[inline]
pub fn iter(&self) -> impl Iterator<Item = &PageTableEntry> {
self.entries.iter()
(0..512).map(move |i| &self.entries[i])
}

/// Returns an iterator that allows modifying the entries of the page table.
#[inline]
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut PageTableEntry> {
self.entries.iter_mut()
// Note that we intentionally don't just return `self.entries.iter()`:
// Some users may choose to create a reference to a page table at
// `0xffff_ffff_ffff_f000`. This causes problems because calculating
// the end pointer of the page tables causes an overflow. Therefore
// creating page tables at that address is unsound and must be avoided.
// Unfortunately creating such page tables is quite common when
// recursive page tables are used, so we try to avoid calculating the
// end pointer if possible. `core::slice::Iter` calculates the end
// pointer to determine when it should stop yielding elements. Because
// we want to avoid calculating the end pointer, we don't use
// `core::slice::Iter`, we implement our own iterator that doesn't
// calculate the end pointer. This doesn't make creating page tables at
// that address sound, but it avoids some easy to trigger
// miscompilations.
let ptr = self.entries.as_mut_ptr();
(0..512).map(move |i| unsafe { &mut *ptr.add(i) })
}

/// Checks if the page table is empty (all entries are zero).
#[inline]
pub fn is_empty(&self) -> bool {
self.entries.iter().all(|entry| entry.is_unused())
self.iter().all(|entry| entry.is_unused())
}
}

Expand Down

0 comments on commit 9e0a8d1

Please sign in to comment.