From b5f94a5a2e23abad184e2b59f217e5203545b527 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 14 Mar 2024 12:15:43 +0100 Subject: [PATCH] Fix bug in the unmapping code Previously trying to funmap an address after the start of the grant would result in an overflow only caught when compiling the kernel with debug assertions enabled. --- src/context/memory.rs | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/context/memory.rs b/src/context/memory.rs index 3a2c66b2d9..cddd71fddb 100644 --- a/src/context/memory.rs +++ b/src/context/memory.rs @@ -521,11 +521,32 @@ impl AddrSpace { let intersection = conflicting_span.intersection(requested_span); requested_span = { - let offset = conflicting_span.base.offset_from(requested_span.base); - PageSpan::new( - conflicting_span.end(), - requested_span.count - offset - conflicting_span.count, - ) + // In the following diagrams [---> indicates a range of + // base..base+count where the [ is at the base and > is at + // base+count. In other words, the [ is part of the range and + // the > is not part of the range. + if conflicting_span.end() < requested_span.end() { + // [------> conflicting_span + // [-------> requested_span + // [---> next requested_span + // or + // [----> conflicting_span + // [----------> requested_span + // [--> next requested_span + PageSpan::new( + conflicting_span.end(), + requested_span.end().offset_from(conflicting_span.end()), + ) + } else { + // [----------> conflicting_span + // [-----> requested_span + // next requested_span + // or + // [--------> conflicting_span + // [--------> requested_span + // next requested_span + PageSpan::empty() + } }; let (before, grant, after) = grant @@ -649,6 +670,9 @@ impl PageSpan { pub fn new(base: Page, count: usize) -> Self { Self { base, count } } + pub fn empty() -> Self { + Self { base: Page::containing_address(VirtualAddress::new(0)), count: 0 } + } pub fn validate_nonempty(address: VirtualAddress, size: usize) -> Option { Self::validate(address, size).filter(|this| !this.is_empty()) }