- Replace arch_cpu_user_strlcpy() and arch_cpu_user_memset() with x86 assembly
  versions. These correctly handle the fault handler, which had broken again
  on gcc4 for the C versions, causing stack corruption in certain error cases.
  The other architectures will still need to have corresponding asm variants
  added in order for them to not run into the same issue though.
This commit is contained in:
Rene Gollent 2012-07-02 02:06:29 -04:00
parent 5dc5dbbbb4
commit fb8447d595
3 changed files with 107 additions and 60 deletions

View File

@ -4,6 +4,7 @@
*
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*
*/
@ -988,65 +989,6 @@ arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages)
}
ssize_t
arch_cpu_user_strlcpy(char *to, const char *from, size_t size,
addr_t *faultHandler)
{
int fromLength = 0;
addr_t oldFaultHandler = *faultHandler;
// this check is to trick the gcc4 compiler and have it keep the error label
if (to == NULL && size > 0)
goto error;
*faultHandler = (addr_t)&&error;
if (size > 0) {
to[--size] = '\0';
// copy
for ( ; size; size--, fromLength++, to++, from++) {
if ((*to = *from) == '\0')
break;
}
}
// count any leftover from chars
while (*from++ != '\0') {
fromLength++;
}
*faultHandler = oldFaultHandler;
return fromLength;
error:
*faultHandler = oldFaultHandler;
return B_BAD_ADDRESS;
}
status_t
arch_cpu_user_memset(void *s, char c, size_t count, addr_t *faultHandler)
{
char *xs = (char *)s;
addr_t oldFaultHandler = *faultHandler;
// this check is to trick the gcc4 compiler and have it keep the error label
if (s == NULL)
goto error;
*faultHandler = (addr_t)&&error;
while (count--)
*xs++ = c;
*faultHandler = oldFaultHandler;
return 0;
error:
*faultHandler = oldFaultHandler;
return B_BAD_ADDRESS;
}
status_t
arch_cpu_shutdown(bool rebootSystem)
{

View File

@ -1,5 +1,6 @@
/*
* Copyright 2003-2007, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
@ -219,6 +220,108 @@ FUNCTION(arch_cpu_user_memcpy):
FUNCTION_END(arch_cpu_user_memcpy)
/* status_t arch_cpu_user_memset(void *to, char c, size_t count, addr_t *faultHandler) */
FUNCTION(arch_cpu_user_memset):
pushl %esi
pushl %edi
movl 12(%esp),%edi /* dest */
movb 16(%esp),%al /* c */
movl 20(%esp),%ecx /* count */
/* set the fault handler */
movl 24(%esp),%edx /* fault handler */
movl (%edx),%esi
movl $.L_user_memset_error, (%edx)
rep
stosb
/* restore the old fault handler */
movl %esi,(%edx)
xor %eax,%eax
popl %edi
popl %esi
ret
/* error condition */
.L_user_memset_error:
/* restore the old fault handler */
movl %esi,(%edx)
movl $-1,%eax /* return a generic error, the wrapper routine will deal with it */
popl %edi
popl %esi
ret
FUNCTION_END(arch_cpu_user_memset)
/* ssize_t arch_cpu_user_strlcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */
FUNCTION(arch_cpu_user_strlcpy):
pushl %esi
pushl %edi
pushl %ebx
movl 16(%esp),%edi /* dest */
movl 20(%esp),%esi /* source */
movl 24(%esp),%ecx /* count */
/* set the fault handler */
movl 28(%esp),%edx /* fault handler */
movl (%edx),%ebx
movl $.L_user_strlcpy_error, (%edx)
/* Check for 0 length */
cmp $0,%ecx
je .L_user_strlcpy_source_count
/* Copy at most count - 1 bytes */
dec %ecx
/* move data by bytes */
cld
repnz
movsb
/* null terminate string */
movb $0,(%edi)
dec %esi
/* check if we copied the entire source string */
cmp $0,%ecx
jne .L_user_strlcpy_source_done
/* count remaining bytes in src */
.L_user_strlcpy_source_count:
not %ecx
movb $0,%al
repnz
scasb
.L_user_strlcpy_source_done:
movl %esi,%eax
subl 20(%esp),%eax
subl $1,%eax
/* restore the old fault handler */
movl %ebx,(%edx)
popl %ebx
popl %edi
popl %esi
ret
/* error condition */
.L_user_strlcpy_error:
/* restore the old fault handler */
movl %ebx,(%edx)
movl $-1,%eax /* return a generic error, the wrapper routine will deal with it */
popl %ebx
popl %edi
popl %esi
ret
FUNCTION_END(arch_cpu_user_strlcpy)
/*! \fn void arch_debug_call_with_fault_handler(cpu_ent* cpu,
jmp_buf jumpBuffer, void (*function)(void*), void* parameter)

View File

@ -5104,8 +5104,10 @@ user_strlcpy(char* to, const char* from, size_t size)
&thread_get_current_thread()->fault_handler);
// If we hit the address overflow boundary, fail.
if (result >= 0 && (size_t)result >= maxSize && maxSize < size)
if (result < 0 || (result >= 0 && (size_t)result >= maxSize
&& maxSize < size)) {
return B_BAD_ADDRESS;
}
return result;
}