From 9c5c5990414f9570d5271328ce67252d50dfe8a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Dziepak?= Date: Mon, 15 Sep 2014 23:18:25 +0200 Subject: [PATCH] kernel: pagecache: provided buffers are not always in user memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Source or destination buffers passed to pagecache functions may belong to kernel memory (e.g. when the caller is packagefs). Because of that we should tell vm_memcpy_{from, to}_physical() truth, not assume that all buffers are in user memory. That's important because user memory page fault handlers cannot be nested and these functions may be used while handling a page fault. With high probability fixes #11246. Signed-off-by: Paweł Dziepak --- src/system/kernel/cache/file_cache.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/system/kernel/cache/file_cache.cpp b/src/system/kernel/cache/file_cache.cpp index 01257d792b..80f5d4174a 100644 --- a/src/system/kernel/cache/file_cache.cpp +++ b/src/system/kernel/cache/file_cache.cpp @@ -434,7 +434,7 @@ read_into_cache(file_cache_ref* ref, void* cookie, off_t offset, vm_memcpy_from_physical((void*)buffer, pages[i]->physical_page_number * B_PAGE_SIZE + pageOffset, - bytes, true); + bytes, IS_USER_ADDRESS(buffer)); buffer += bytes; bufferSize -= bytes; @@ -588,7 +588,7 @@ write_to_cache(file_cache_ref* ref, void* cookie, off_t offset, if (useBuffer) { // copy data from user buffer vm_memcpy_to_physical(base + pageOffset, (void*)buffer, bytes, - true); + IS_USER_ADDRESS(buffer)); } else { // clear buffer instead vm_memset_physical(base + pageOffset, 0, bytes); @@ -808,16 +808,17 @@ cache_io(void* _cacheRef, void* cookie, off_t offset, addr_t buffer, phys_addr_t pageAddress = (phys_addr_t)page->physical_page_number * B_PAGE_SIZE + pageOffset; + bool userBuffer = IS_USER_ADDRESS(buffer); if (doWrite) { if (useBuffer) { vm_memcpy_to_physical(pageAddress, (void*)buffer, - bytesInPage, true); + bytesInPage, userBuffer); } else { vm_memset_physical(pageAddress, 0, bytesInPage); } } else if (useBuffer) { vm_memcpy_from_physical((void*)buffer, pageAddress, - bytesInPage, true); + bytesInPage, userBuffer); } locker.Lock();