From 310f367fb1174117c42b1e13d695149f52e7287f Mon Sep 17 00:00:00 2001 From: kd-11 <15904127+kd-11@users.noreply.github.com> Date: Thu, 14 May 2020 14:57:58 +0300 Subject: [PATCH] rsx: Improve blit engine memory validation (#8215) - In blit engine logic there is a tendancy to over-allocate so as to avoid having to sticth together textures later - Sometimes this can lead to out of bounds access and crash applications, so memory must be validated --- rpcs3/Emu/RSX/Common/texture_cache.h | 50 +++++++++++++++++++++------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index a3fbc9ead..514dc4bb3 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -2060,6 +2060,35 @@ namespace rsx return {}; }; + auto validate_memory_range = [](u32 base_address, u32 write_end, u32 heurestic_end) + { + if (heurestic_end <= write_end) + { + return true; + } + + // Confirm if the pages actually exist in vm + if (get_location(base_address) == CELL_GCM_LOCATION_LOCAL) + { + const auto vram_end = rsx::get_current_renderer()->local_mem_size + rsx::constants::local_mem_base; + if (heurestic_end > vram_end) + { + // Outside available VRAM area + return false; + } + } + else + { + if (!vm::check_addr(write_end, (heurestic_end - write_end), vm::page_info_t::page_allocated)) + { + // Enforce strict allocation size! + return false; + } + } + + return true; + }; + // Check if src/dst are parts of render targets typename surface_store_type::surface_overlap_info dst_subres; bool use_null_region = false; @@ -2470,7 +2499,13 @@ namespace rsx u16 image_width = full_width; u16 image_height = src.height; - if (dst.scale_x > 0.f && dst.scale_y > 0.f) [[likely]] + // Check if memory is valid + const bool use_full_range = validate_memory_range( + image_base, + (src_address + src_payload_length), + image_base + (image_height * src.pitch)); + + if (use_full_range && dst.scale_x > 0.f && dst.scale_y > 0.f) [[likely]] { // Loading full image from the corner address // Translate src_area into the declared block @@ -2565,18 +2600,9 @@ namespace rsx u32 block_end = dst_base_address + (dst.pitch * dst_dimensions.height); // Confirm if the pages actually exist in vm - // Only need to test the extra padding memory and only when its on main memory - // NOTE: When src is not a render target, padding is not added speculatively - if (src_is_render_target && get_location(dst_base_address) != CELL_GCM_LOCATION_LOCAL) + if (!validate_memory_range(dst_base_address, write_end, block_end)) { - if (block_end > write_end) - { - if (!vm::check_addr(write_end, (block_end - write_end), vm::page_info_t::page_allocated)) - { - // Enforce strict allocation size! - block_end = write_end; - } - } + block_end = write_end; } const u32 usable_section_length = std::max(write_end, block_end) - dst_base_address;