diff --git a/kernel/src/memory/frame_metadata.rs b/kernel/src/memory/frame_metadata.rs index d93b6e5..8ff04a1 100644 --- a/kernel/src/memory/frame_metadata.rs +++ b/kernel/src/memory/frame_metadata.rs @@ -76,9 +76,20 @@ pub fn frame_decref(frame: PhysFrame) -> bool { // old_count > 1, still shared false } else { - // Frame wasn't tracked - this is the sole owner - // Return true to indicate it can be freed - true + // Frame wasn't tracked in CoW metadata. + // This could be: + // 1. A frame allocated by a child process after fork (could be freed) + // 2. A frame that was never part of CoW sharing (might be unsafe to free) + // + // SAFETY: Don't free untracked frames. This causes a memory leak for + // child-allocated pages, but prevents potential corruption if the frame + // is still in use by something else. The root cause needs further + // investigation. + log::trace!( + "frame_decref: frame {:#x} not tracked, refusing to free (leak to prevent corruption)", + addr + ); + false } } diff --git a/kernel/src/process/process.rs b/kernel/src/process/process.rs index 3d9a08e..e5ebd0b 100644 --- a/kernel/src/process/process.rs +++ b/kernel/src/process/process.rs @@ -291,7 +291,9 @@ impl Process { let frame = PhysFrame::containing_address(phys_addr); // Decrement reference count - // If this was the last reference, deallocate the frame + // If this was the last reference (frame was tracked and refcount reached 0), + // deallocate the frame. frame_decref returns false for untracked frames + // to prevent corruption from freeing potentially in-use frames. if frame_decref(frame) { deallocate_frame(frame); freed_count += 1;