From 54732edff4d44e0fe8c9b9c808d469557b5f0aa7 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sun, 15 Sep 2024 23:18:05 +0300 Subject: [PATCH] Kernel: Fix bugs in memory regions MemoryRegion::initialize() required size to be page aligned, this is not necessary. MemoryBackedRegion::copy_data_to_region() required user-write permissions for underlying data. This did not matter as memory backed regions dont support COW memory, but it could lead to bugs later on. --- kernel/kernel/Memory/MemoryBackedRegion.cpp | 14 ++++++++++++-- kernel/kernel/Memory/MemoryRegion.cpp | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/kernel/kernel/Memory/MemoryBackedRegion.cpp b/kernel/kernel/Memory/MemoryBackedRegion.cpp index ede8fa5a..47e0bdf9 100644 --- a/kernel/kernel/Memory/MemoryBackedRegion.cpp +++ b/kernel/kernel/Memory/MemoryBackedRegion.cpp @@ -94,9 +94,19 @@ namespace Kernel vaddr_t page_offset = write_vaddr % PAGE_SIZE; size_t bytes = BAN::Math::min(buffer_size - written, PAGE_SIZE - page_offset); - TRY(allocate_page_containing(write_vaddr, true)); + paddr_t paddr = m_page_table.physical_address_of(write_vaddr & PAGE_ADDR_MASK); + if (paddr == 0) + { + if (!TRY(allocate_page_containing(write_vaddr, false))) + { + dwarnln("Could not allocate page for data copying"); + return BAN::Error::from_errno(EFAULT); + } + paddr = m_page_table.physical_address_of(write_vaddr & PAGE_ADDR_MASK); + ASSERT(paddr); + } - PageTable::with_fast_page(m_page_table.physical_address_of(write_vaddr & PAGE_ADDR_MASK), [&] { + PageTable::with_fast_page(paddr, [&] { memcpy(PageTable::fast_page_as_ptr(page_offset), (void*)(buffer + written), bytes); }); diff --git a/kernel/kernel/Memory/MemoryRegion.cpp b/kernel/kernel/Memory/MemoryRegion.cpp index 1dfb2b4d..82376021 100644 --- a/kernel/kernel/Memory/MemoryRegion.cpp +++ b/kernel/kernel/Memory/MemoryRegion.cpp @@ -23,7 +23,7 @@ namespace Kernel m_vaddr = m_page_table.reserve_free_contiguous_pages(needed_pages, address_range.start); if (m_vaddr == 0) return BAN::Error::from_errno(ENOMEM); - if (m_vaddr + needed_pages * PAGE_SIZE > address_range.end) + if (m_vaddr + m_size > address_range.end) return BAN::Error::from_errno(ENOMEM); return {}; }