diff options
Diffstat (limited to 'Kernel/VM')
-rw-r--r-- | Kernel/VM/InodeVMObject.cpp | 2 | ||||
-rw-r--r-- | Kernel/VM/InodeVMObject.h | 2 | ||||
-rw-r--r-- | Kernel/VM/MemoryManager.cpp | 33 | ||||
-rw-r--r-- | Kernel/VM/MemoryManager.h | 6 | ||||
-rw-r--r-- | Kernel/VM/Region.cpp | 30 | ||||
-rw-r--r-- | Kernel/VM/Region.h | 1 |
6 files changed, 28 insertions, 46 deletions
diff --git a/Kernel/VM/InodeVMObject.cpp b/Kernel/VM/InodeVMObject.cpp index 8c5b07d413..c63417fab0 100644 --- a/Kernel/VM/InodeVMObject.cpp +++ b/Kernel/VM/InodeVMObject.cpp @@ -89,7 +89,7 @@ void InodeVMObject::inode_size_changed(Badge<Inode>, size_t old_size, size_t new }); } -void InodeVMObject::inode_contents_changed(Badge<Inode>, off_t offset, ssize_t size, const u8* data) +void InodeVMObject::inode_contents_changed(Badge<Inode>, off_t offset, ssize_t size, const UserOrKernelBuffer& data) { (void)size; (void)data; diff --git a/Kernel/VM/InodeVMObject.h b/Kernel/VM/InodeVMObject.h index 727199ff7e..94e7073709 100644 --- a/Kernel/VM/InodeVMObject.h +++ b/Kernel/VM/InodeVMObject.h @@ -39,7 +39,7 @@ public: Inode& inode() { return *m_inode; } const Inode& inode() const { return *m_inode; } - void inode_contents_changed(Badge<Inode>, off_t, ssize_t, const u8*); + void inode_contents_changed(Badge<Inode>, off_t, ssize_t, const UserOrKernelBuffer&); void inode_size_changed(Badge<Inode>, size_t old_size, size_t new_size); size_t amount_dirty() const; diff --git a/Kernel/VM/MemoryManager.cpp b/Kernel/VM/MemoryManager.cpp index 88bb451435..fc5114f296 100644 --- a/Kernel/VM/MemoryManager.cpp +++ b/Kernel/VM/MemoryManager.cpp @@ -767,39 +767,6 @@ bool MemoryManager::validate_user_stack(const Process& process, VirtualAddress v return region && region->is_user_accessible() && region->is_stack(); } -bool MemoryManager::validate_kernel_read(const Process& process, VirtualAddress vaddr, size_t size) const -{ - ScopedSpinLock lock(s_mm_lock); - return validate_range<AccessSpace::Kernel, AccessType::Read>(process, vaddr, size); -} - -bool MemoryManager::can_read_without_faulting(const Process& process, VirtualAddress vaddr, size_t size) const -{ - // FIXME: Use the size argument! - UNUSED_PARAM(size); - ScopedSpinLock lock(s_mm_lock); - auto* pte = const_cast<MemoryManager*>(this)->pte(process.page_directory(), vaddr); - if (!pte) - return false; - return pte->is_present(); -} - -bool MemoryManager::validate_user_read(const Process& process, VirtualAddress vaddr, size_t size) const -{ - if (!is_user_address(vaddr)) - return false; - ScopedSpinLock lock(s_mm_lock); - return validate_range<AccessSpace::User, AccessType::Read>(process, vaddr, size); -} - -bool MemoryManager::validate_user_write(const Process& process, VirtualAddress vaddr, size_t size) const -{ - if (!is_user_address(vaddr)) - return false; - ScopedSpinLock lock(s_mm_lock); - return validate_range<AccessSpace::User, AccessType::Write>(process, vaddr, size); -} - void MemoryManager::register_vmobject(VMObject& vmobject) { ScopedSpinLock lock(s_mm_lock); diff --git a/Kernel/VM/MemoryManager.h b/Kernel/VM/MemoryManager.h index f3f4bbb90c..d9823377ab 100644 --- a/Kernel/VM/MemoryManager.h +++ b/Kernel/VM/MemoryManager.h @@ -100,12 +100,6 @@ public: void enter_process_paging_scope(Process&); bool validate_user_stack(const Process&, VirtualAddress) const; - bool validate_user_read(const Process&, VirtualAddress, size_t) const; - bool validate_user_write(const Process&, VirtualAddress, size_t) const; - - bool validate_kernel_read(const Process&, VirtualAddress, size_t) const; - - bool can_read_without_faulting(const Process&, VirtualAddress, size_t) const; enum class ShouldZeroFill { No, diff --git a/Kernel/VM/Region.cpp b/Kernel/VM/Region.cpp index d3b4d02676..a1d39daf24 100644 --- a/Kernel/VM/Region.cpp +++ b/Kernel/VM/Region.cpp @@ -439,13 +439,24 @@ PageFaultResponse Region::handle_cow_fault(size_t page_index_in_region) klog() << "MM: handle_cow_fault was unable to allocate a physical page"; return PageFaultResponse::OutOfMemory; } - auto physical_page_to_copy = move(page_slot); + u8* dest_ptr = MM.quickmap_page(*page); const u8* src_ptr = vaddr().offset(page_index_in_region * PAGE_SIZE).as_ptr(); #ifdef PAGE_FAULT_DEBUG - dbg() << " >> COW " << page->paddr() << " <- " << physical_page_to_copy->paddr(); + dbg() << " >> COW " << page->paddr() << " <- " << page_slot->paddr(); #endif - copy_from_user(dest_ptr, src_ptr, PAGE_SIZE); + { + SmapDisabler disabler; + void* fault_at; + if (!safe_memcpy(dest_ptr, src_ptr, PAGE_SIZE, fault_at)) { + if ((u8*)fault_at >= dest_ptr && (u8*)fault_at <= dest_ptr + PAGE_SIZE) + dbg() << " >> COW: error copying page " << page_slot->paddr() << "/" << VirtualAddress(src_ptr) << " to " << page->paddr() << "/" << VirtualAddress(dest_ptr) << ": failed to write to page at " << VirtualAddress(fault_at); + else if ((u8*)fault_at >= src_ptr && (u8*)fault_at <= src_ptr + PAGE_SIZE) + dbg() << " >> COW: error copying page " << page_slot->paddr() << "/" << VirtualAddress(src_ptr) << " to " << page->paddr() << "/" << VirtualAddress(dest_ptr) << ": failed to read from page at " << VirtualAddress(fault_at); + else + ASSERT_NOT_REACHED(); + } + } page_slot = move(page); MM.unquickmap_page(); set_should_cow(page_index_in_region, false); @@ -489,7 +500,8 @@ PageFaultResponse Region::handle_inode_fault(size_t page_index_in_region) sti(); u8 page_buffer[PAGE_SIZE]; auto& inode = inode_vmobject.inode(); - auto nread = inode.read_bytes((first_page_index() + page_index_in_region) * PAGE_SIZE, PAGE_SIZE, page_buffer, nullptr); + auto buffer = UserOrKernelBuffer::for_kernel_buffer(page_buffer); + auto nread = inode.read_bytes((first_page_index() + page_index_in_region) * PAGE_SIZE, PAGE_SIZE, buffer, nullptr); if (nread < 0) { klog() << "MM: handle_inode_fault had error (" << nread << ") while reading!"; return PageFaultResponse::ShouldCrash; @@ -506,7 +518,15 @@ PageFaultResponse Region::handle_inode_fault(size_t page_index_in_region) } u8* dest_ptr = MM.quickmap_page(*vmobject_physical_page_entry); - memcpy(dest_ptr, page_buffer, PAGE_SIZE); + { + void* fault_at; + if (!safe_memcpy(dest_ptr, page_buffer, PAGE_SIZE, fault_at)) { + if ((u8*)fault_at >= dest_ptr && (u8*)fault_at <= dest_ptr + PAGE_SIZE) + dbg() << " >> inode fault: error copying data to " << vmobject_physical_page_entry->paddr() << "/" << VirtualAddress(dest_ptr) << ", failed at " << VirtualAddress(fault_at); + else + ASSERT_NOT_REACHED(); + } + } MM.unquickmap_page(); remap_page(page_index_in_region); diff --git a/Kernel/VM/Region.h b/Kernel/VM/Region.h index 5480e186de..68d40e53c3 100644 --- a/Kernel/VM/Region.h +++ b/Kernel/VM/Region.h @@ -79,6 +79,7 @@ public: unsigned access() const { return m_access; } void set_name(const String& name) { m_name = name; } + void set_name(String&& name) { m_name = move(name); } const VMObject& vmobject() const { return *m_vmobject; } VMObject& vmobject() { return *m_vmobject; } |