Made the {debug,user}_{mem,strl}cpy() and user_memset() functions deal with
address overflows. Apparently at least the x86 string instructions generate a general protection fault instead of a page fault, and we only use the fault handler in the latter case (maybe we should change that, too). Fixes #4714. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33436 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
4401e83384
commit
8a71915a9d
@ -13,6 +13,8 @@
|
||||
|
||||
#include "blue_screen.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <cpu.h>
|
||||
#include <debug.h>
|
||||
#include <debug_heap.h>
|
||||
@ -1529,6 +1531,10 @@ debug_call_with_fault_handler(jmp_buf jumpBuffer, void (*function)(void*),
|
||||
status_t
|
||||
debug_memcpy(void* to, const void* from, size_t size)
|
||||
{
|
||||
// don't allow address overflows
|
||||
if ((addr_t)from + size < (addr_t)from || (addr_t)to + size < (addr_t)to)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
debug_memcpy_parameters parameters = {to, from, size};
|
||||
|
||||
if (debug_call_with_fault_handler(gCPU[sDebuggerOnCPU].fault_jump_buffer,
|
||||
@ -1545,12 +1551,26 @@ debug_memcpy(void* to, const void* from, size_t size)
|
||||
ssize_t
|
||||
debug_strlcpy(char* to, const char* from, size_t size)
|
||||
{
|
||||
debug_strlcpy_parameters parameters = {to, from, size};
|
||||
if (size == 0)
|
||||
return 0;
|
||||
if (from == NULL || to == NULL)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
// limit size to avoid address overflows
|
||||
size_t maxSize = std::min(size,
|
||||
~(addr_t)0 - std::max((addr_t)from, (addr_t)to) + 1);
|
||||
|
||||
debug_strlcpy_parameters parameters = {to, from, maxSize};
|
||||
|
||||
if (debug_call_with_fault_handler(gCPU[sDebuggerOnCPU].fault_jump_buffer,
|
||||
&debug_strlcpy_trampoline, ¶meters) != 0) {
|
||||
return B_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
// If we hit the address overflow boundary, fail.
|
||||
if (parameters.result == maxSize && maxSize < size)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
return parameters.result;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <OS.h>
|
||||
#include <KernelExport.h>
|
||||
|
||||
@ -5457,6 +5459,10 @@ vm_memcpy_physical_page(addr_t to, addr_t from)
|
||||
status_t
|
||||
user_memcpy(void* to, const void* from, size_t size)
|
||||
{
|
||||
// don't allow address overflows
|
||||
if ((addr_t)from + size < (addr_t)from || (addr_t)to + size < (addr_t)to)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
if (arch_cpu_user_memcpy(to, from, size,
|
||||
&thread_get_current_thread()->fault_handler) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
@ -5477,14 +5483,34 @@ user_memcpy(void* to, const void* from, size_t size)
|
||||
ssize_t
|
||||
user_strlcpy(char* to, const char* from, size_t size)
|
||||
{
|
||||
return arch_cpu_user_strlcpy(to, from, size,
|
||||
if (size == 0)
|
||||
return 0;
|
||||
if (from == NULL || to == NULL)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
// limit size to avoid address overflows
|
||||
size_t maxSize = std::min(size,
|
||||
~(addr_t)0 - std::max((addr_t)from, (addr_t)to) + 1);
|
||||
|
||||
|
||||
ssize_t result = arch_cpu_user_strlcpy(to, from, maxSize,
|
||||
&thread_get_current_thread()->fault_handler);
|
||||
|
||||
// If we hit the address overflow boundary, fail.
|
||||
if (result >= 0 && (size_t)result == maxSize && maxSize < size)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
user_memset(void* s, char c, size_t count)
|
||||
{
|
||||
// don't allow address overflows
|
||||
if ((addr_t)s + count < (addr_t)s)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
if (arch_cpu_user_memset(s, c, count,
|
||||
&thread_get_current_thread()->fault_handler) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
Loading…
x
Reference in New Issue
Block a user