rsx: Fix memory tagging and add some security checks

This commit is contained in:
kd-11 2022-02-06 23:30:31 +03:00 committed by kd-11
parent 987166f4da
commit 247759b75b

View file

@ -660,48 +660,61 @@ namespace rsx
void remove_duplicates_fallback_impl(std::vector<surface_overlap_info>& sections, const rsx::address_range& range) void remove_duplicates_fallback_impl(std::vector<surface_overlap_info>& sections, const rsx::address_range& range)
{ {
// Originally used to debug crashes but this function breaks often enough that I'll leave the checks in for now.
// Safe to remove after some time if no asserts are reported.
constexpr u32 overrun_cookie_value = 0xCAFEBABEu;
// Generic painter's algorithm to detect obsolete sections // Generic painter's algorithm to detect obsolete sections
ensure(range.length() < 64 * 0x100000); ensure(range.length() < 64 * 0x100000);
std::vector<u8> marker(range.length(), 0); std::vector<u8> marker(range.length() + sizeof(overrun_cookie_value), 0);
auto compare_and_tag_row = [&](u32 offset, u32 length) -> bool // Tag end
u32* overrun_test_ptr = utils::bless<u32>(marker.data() + range.length());
*overrun_test_ptr = overrun_cookie_value;
auto compare_and_tag_row = [&](const u32 offset, u32 length) -> bool
{ {
bool valid = false; u64 mask = 0;
for (u32 i = 0; i < (length / 8); ++i, offset += 8, length -= 8) u8* dst_ptr = marker.data() + offset;
while (length >= 8)
{ {
auto dest = reinterpret_cast<u64*>(marker.data() + offset); auto& value = *utils::bless<u64>(dst_ptr);
valid |= (*dest != umax); mask |= (~value); // If the value is not all 1s, set valid to true
*dest = umax; value = umax;
dst_ptr += 8;
length -= 8;
} }
if (length >= 4) if (length >= 4)
{ {
auto dest = reinterpret_cast<u32*>(marker.data() + offset); auto& value = *utils::bless<u32>(dst_ptr);
valid |= (*dest != umax); mask |= (~value);
*dest = umax; value = umax;
offset += 4; dst_ptr += 4;
length -= 4; length -= 4;
} }
if (length >= 2) if (length >= 2)
{ {
auto dest = reinterpret_cast<u16*>(marker.data() + offset); auto& value = *utils::bless<u16>(dst_ptr);
valid |= (*dest != umax); mask |= (~value);
*dest = umax; value = umax;
offset += 2; dst_ptr += 2;
length -= 2; length -= 2;
} }
if (length) if (length)
{ {
auto dest = (marker.data() + offset); auto& value = *dst_ptr;
valid |= (*dest != umax); mask |= (~value);
*dest = umax; value = umax;
} }
return valid; return !!mask;
}; };
for (auto it = sections.crbegin(); it != sections.crend(); ++it) for (auto it = sections.crbegin(); it != sections.crend(); ++it)
@ -750,9 +763,11 @@ namespace rsx
num_rows = utils::aligned_div(this_range.length(), rsx_pitch); num_rows = utils::aligned_div(this_range.length(), rsx_pitch);
} }
for (u32 row = 0, offset = (this_range.start - range.start); row < num_rows; ++row, offset += rsx_pitch) for (u32 row = 0, offset = (this_range.start - range.start), section_len = (this_range.end - range.start + 1);
row < num_rows;
++row, offset += rsx_pitch)
{ {
valid |= compare_and_tag_row(offset, std::min<u32>(native_pitch, (this_range.end - offset + 1))); valid |= compare_and_tag_row(offset, std::min<u32>(native_pitch, (section_len - offset)));
} }
if (!valid) if (!valid)
@ -761,6 +776,9 @@ namespace rsx
invalidate_surface_address(it->base_address, it->is_depth); invalidate_surface_address(it->base_address, it->is_depth);
} }
} }
// Verify no OOB
ensure(*overrun_test_ptr == overrun_cookie_value);
} }
protected: protected: