UserVM: Validate the entire range when freeing multiple VM pages
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2023-01-16 21:16:38 +01:00
parent 631cdd0204
commit a3d0fa7d0a
Signed by: apio
GPG Key ID: B8A7D06E42258954
3 changed files with 40 additions and 2 deletions

View File

@ -100,8 +100,7 @@ Result<void> UserVM::free_several_pages(u64 address, usize count)
const u64 index = (address - VM_BASE) / ARCH_PAGE_SIZE;
if ((index + count) > (MAX_VM_SIZE * 8)) return err(EINVAL);
// FIXME: Is it necessary to check all pages?
if (!m_bitmap.get(index)) return err(EFAULT);
if (!m_bitmap.match_region(index, count, true)) return err(EFAULT);
m_bitmap.clear_region(index, count, false);

View File

@ -43,6 +43,8 @@ class Bitmap
Option<usize> find_and_toggle_region(bool value, usize count, usize begin = 0);
bool match_region(usize start, usize bits, bool value);
void clear(bool value);
void clear_region(usize start, usize bits, bool value);

View File

@ -167,3 +167,40 @@ Option<usize> Bitmap::find_and_toggle_region(bool value, usize count, usize begi
clear_region(index, count, !value);
return index;
}
bool Bitmap::match_region(usize start, usize bits, bool value)
{
expect(initialized(), "Bitmap was never initialized");
expect((start + bits) <= size(), "Bitmap match out of range");
if (!bits) return true;
// Match individual bits while not on a byte boundary.
while ((start % 8) && bits)
{
if (get(start) != value) return false;
start++;
bits--;
}
// Match the rest in bytes.
usize bytes = bits / 8;
const u8 byte_that_contains_only_value = value_byte(value);
for (usize i = start; i < start + bytes; i += 8)
{
if (m_location[i / 8] != byte_that_contains_only_value) return false;
}
start += bytes * 8;
bits -= bytes * 8;
// Match the remaining individual bits.
while (bits--)
{
if (get(start) != value) return false;
start++;
}
return true;
}