kernel: replace 5 unreachable!() in page fault handler with graceful errors

- 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.
This commit is contained in:
2026-07-10 09:23:12 +03:00
parent 165e3c478f
commit 30e9235e44
+20 -7
View File
@@ -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?