diff --git a/src/system/kernel/arch/x86/arch_cpu.c b/src/system/kernel/arch/x86/arch_cpu.c index 8640c4dd13..3ba3224b9a 100644 --- a/src/system/kernel/arch/x86/arch_cpu.c +++ b/src/system/kernel/arch/x86/arch_cpu.c @@ -580,32 +580,6 @@ arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages) } } - -status_t -arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *faultHandler) -{ - char *tmp = (char *)to; - char *s = (char *)from; - addr_t oldFaultHandler = *faultHandler; - - // this check is to trick the gcc4 compiler and have it keep the error label - if (to == NULL) - goto error; - - *faultHandler = (addr_t)&&error; - - while (size--) - *tmp++ = *s++; - - *faultHandler = oldFaultHandler; - return 0; - -error: - *faultHandler = oldFaultHandler; - return B_BAD_ADDRESS; -} - - ssize_t arch_cpu_user_strlcpy(char *to, const char *from, size_t size, addr_t *faultHandler) { diff --git a/src/system/kernel/arch/x86/arch_x86.S b/src/system/kernel/arch/x86/arch_x86.S index 97e591bed2..5920c8c500 100644 --- a/src/system/kernel/arch/x86/arch_x86.S +++ b/src/system/kernel/arch/x86/arch_x86.S @@ -219,3 +219,46 @@ FUNCTION(arch_debug_save_registers): popl %eax popl %esi ret + +/* status_t arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */ +FUNCTION(arch_cpu_user_memcpy): + pushl %esi + pushl %edi + movl 12(%esp),%edi /* dest */ + movl 16(%esp),%esi /* source */ + movl 20(%esp),%ecx /* count */ + + /* set the fault handler */ + movl 24(%esp),%edx /* fault handler */ + movl (%edx),%eax + movl $.L_user_memcpy_error, (%edx) + + /* move by words */ + cld + shrl $2,%ecx + rep + movsl + + /* move any remaining data by bytes */ + movl 20(%esp),%ecx + andl $3,%ecx + rep + movsb + + /* restore the old fault handler */ + movl %eax,(%edx) + xor %eax,%eax + + popl %edi + popl %esi + ret + + /* error condition */ +.L_user_memcpy_error: + /* restore the old fault handler */ + movl %eax,(%edx) + movl $-1,%eax /* return a generic error, the wrapper routine will deal with it */ + popl %edi + popl %esi + ret + diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index 8274d87ead..00d70dcc3f 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -3741,7 +3741,9 @@ test_lock_memory(vm_address_space *addressSpace, addr_t address, status_t user_memcpy(void *to, const void *from, size_t size) { - return arch_cpu_user_memcpy(to, from, size, &thread_get_current_thread()->fault_handler); + if (arch_cpu_user_memcpy(to, from, size, &thread_get_current_thread()->fault_handler) < B_OK) + return B_BAD_ADDRESS; + return B_OK; } @@ -3765,10 +3767,11 @@ user_strlcpy(char *to, const char *from, size_t size) status_t user_memset(void *s, char c, size_t count) { - return arch_cpu_user_memset(s, c, count, &thread_get_current_thread()->fault_handler); + if (arch_cpu_user_memset(s, c, count, &thread_get_current_thread()->fault_handler) < B_OK) + return B_BAD_ADDRESS; + return B_OK; } - // #pragma mark - kernel public API