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)
|
||||
/// 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
|
||||
|
||||
Reference in New Issue
Block a user