From 30e9235e44c67398b263286dd60010ed32e0d151 Mon Sep 17 00:00:00 2001 From: vasilito Date: Fri, 10 Jul 2026 09:23:12 +0300 Subject: [PATCH] kernel: replace 5 unreachable!() in page fault handler with graceful errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SharedToCow/CowToShared invariant violations: log error, return ENOMEM - Allocated page with no frame: log error, return EINVAL (process gets SIGSEGV but kernel survives) Previously these panicked the kernel. Now they handle the rare invariant violation gracefully — same approach as the OOM fix. --- src/context/memory.rs | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/context/memory.rs b/src/context/memory.rs index 93446ba7a7..8ac4c43089 100644 --- a/src/context/memory.rs +++ b/src/context/memory.rs @@ -553,10 +553,14 @@ impl AddrSpaceWrapper { { Ok(_) => Ok(unsafe { RaiiFrame::new_unchecked(frame) }), Err(AddRefError::RcOverflow) => Err(Error::new(ENOMEM)), - Err(AddRefError::SharedToCow) => unreachable!(), - Err(AddRefError::CowToShared) => unreachable!( - "if it was CoW, it was read-only, but in that case we already called correct_inner" - ), + Err(AddRefError::SharedToCow) => { + log::error!("unexpected SharedToCow in add_ref — invariant violation"); + Err(Error::new(ENOMEM)) + } + Err(AddRefError::CowToShared) => { + log::error!("unexpected CowToShared in add_ref — invariant violation"); + Err(Error::new(ENOMEM)) + } }; drop(guard_lock); @@ -1499,7 +1503,10 @@ impl Grant { new_cow_frame }, - Err(AddRefError::SharedToCow) => unreachable!(), + Err(AddRefError::SharedToCow) => { + log::error!("unexpected SharedToCow in CoW path — invariant violation"); + return Err(Error::new(ENOMEM)); + }, Err(AddRefError::RcOverflow) => return Err(Error::new(ENOMEM)), } } else { @@ -2512,7 +2519,10 @@ fn correct_inner<'l>( if access == AccessMode::Write => { match faulting_pageinfo_opt { - Some((_, None)) => unreachable!("allocated page needs frame to be valid"), + Some((_, None)) => { + log::error!("allocated page has no frame — kernel invariant violation"); + return Err(Error::new(EINVAL)); + } Some((frame, Some(info))) => { if info.allows_writable() { frame @@ -2535,7 +2545,10 @@ fn correct_inner<'l>( Provider::Allocated { .. } | Provider::AllocatedShared { .. } => { match faulting_pageinfo_opt { - Some((_, None)) => unreachable!("allocated page needs frame to be valid"), + Some((_, None)) => { + log::error!("allocated page has no frame — kernel invariant violation"); + return Err(Error::new(EINVAL)); + } // TODO: Can this match arm even be reached? In other words, can the TLB cache // remember that pages are not present?