Merge audit-2026-05-fix/p1-xmodbug-002-write-bulk

This commit is contained in:
MechaCat02
2026-05-03 14:30:22 +02:00

View File

@@ -318,11 +318,33 @@ impl GuestMemory {
/// different threads. Used by the XEX loader (init, single-thread)
/// and `NtReadFile` (mid-execution; the file's destination buffer is
/// guest-thread-private by construction).
///
/// XMODBUG-002: bumps `page_versions` for every page the write
/// touches. Pre-fix, callers like `NtReadFile` could rewrite a page
/// containing texture or shader bytes that a downstream cache had
/// already keyed on the prior version — the cache would happily
/// hand back the stale decoded bytes. The per-byte `write_*` methods
/// already bump the version after their store; this is the bulk
/// equivalent. Reservation-table invalidation for `lwarx`/`stwcx.`
/// remains the caller's responsibility (the table isn't reachable
/// from `GuestMemory` without a wider plumbing change).
pub fn write_bulk(&self, addr: u32, buf: &[u8]) {
let ptr = self.translate_virtual_mut(addr);
unsafe {
std::ptr::copy_nonoverlapping(buf.as_ptr(), ptr, buf.len());
}
if buf.is_empty() {
return;
}
let last_byte = addr.saturating_add(buf.len() as u32).saturating_sub(1);
let first_page = addr / PAGE_SIZE;
let last_page = last_byte / PAGE_SIZE;
for page in first_page..=last_page {
// Use the page-aligned address; bump_page_version computes
// the slot index by `addr / PAGE_SIZE` so any address within
// the page works.
self.bump_page_version(page * PAGE_SIZE);
}
}
/// Check if a guest address has been allocated/committed. Acquire load