Merge audit-2026-05-fix/p1-xmodbug-002-write-bulk
This commit is contained in:
@@ -318,11 +318,33 @@ impl GuestMemory {
|
|||||||
/// different threads. Used by the XEX loader (init, single-thread)
|
/// different threads. Used by the XEX loader (init, single-thread)
|
||||||
/// and `NtReadFile` (mid-execution; the file's destination buffer is
|
/// and `NtReadFile` (mid-execution; the file's destination buffer is
|
||||||
/// guest-thread-private by construction).
|
/// 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]) {
|
pub fn write_bulk(&self, addr: u32, buf: &[u8]) {
|
||||||
let ptr = self.translate_virtual_mut(addr);
|
let ptr = self.translate_virtual_mut(addr);
|
||||||
unsafe {
|
unsafe {
|
||||||
std::ptr::copy_nonoverlapping(buf.as_ptr(), ptr, buf.len());
|
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
|
/// Check if a guest address has been allocated/committed. Acquire load
|
||||||
|
|||||||
Reference in New Issue
Block a user