um: Rework uaccess code
Rework UML's uaccess code to reuse as much as possible from asm-generic/uaccess.c. Signed-off-by: Richard Weinberger <richard@nod.at>
This commit is contained in:
@@ -87,10 +87,10 @@ static int do_op_one_page(unsigned long addr, int len, int is_write,
|
||||
return n;
|
||||
}
|
||||
|
||||
static int buffer_op(unsigned long addr, int len, int is_write,
|
||||
int (*op)(unsigned long, int, void *), void *arg)
|
||||
static long buffer_op(unsigned long addr, int len, int is_write,
|
||||
int (*op)(unsigned long, int, void *), void *arg)
|
||||
{
|
||||
int size, remain, n;
|
||||
long size, remain, n;
|
||||
|
||||
size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
|
||||
remain = len;
|
||||
@@ -139,18 +139,16 @@ static int copy_chunk_from_user(unsigned long from, int len, void *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int copy_from_user(void *to, const void __user *from, int n)
|
||||
long __copy_from_user(void *to, const void __user *from, unsigned long n)
|
||||
{
|
||||
if (segment_eq(get_fs(), KERNEL_DS)) {
|
||||
memcpy(to, (__force void*)from, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return access_ok(VERIFY_READ, from, n) ?
|
||||
buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to):
|
||||
n;
|
||||
return buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to);
|
||||
}
|
||||
EXPORT_SYMBOL(copy_from_user);
|
||||
EXPORT_SYMBOL(__copy_from_user);
|
||||
|
||||
static int copy_chunk_to_user(unsigned long to, int len, void *arg)
|
||||
{
|
||||
@@ -161,18 +159,16 @@ static int copy_chunk_to_user(unsigned long to, int len, void *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int copy_to_user(void __user *to, const void *from, int n)
|
||||
long __copy_to_user(void __user *to, const void *from, unsigned long n)
|
||||
{
|
||||
if (segment_eq(get_fs(), KERNEL_DS)) {
|
||||
memcpy((__force void *) to, from, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return access_ok(VERIFY_WRITE, to, n) ?
|
||||
buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) :
|
||||
n;
|
||||
return buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from);
|
||||
}
|
||||
EXPORT_SYMBOL(copy_to_user);
|
||||
EXPORT_SYMBOL(__copy_to_user);
|
||||
|
||||
static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
|
||||
{
|
||||
@@ -188,9 +184,9 @@ static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int strncpy_from_user(char *dst, const char __user *src, int count)
|
||||
long __strncpy_from_user(char *dst, const char __user *src, long count)
|
||||
{
|
||||
int n;
|
||||
long n;
|
||||
char *ptr = dst;
|
||||
|
||||
if (segment_eq(get_fs(), KERNEL_DS)) {
|
||||
@@ -198,16 +194,13 @@ int strncpy_from_user(char *dst, const char __user *src, int count)
|
||||
return strnlen(dst, count);
|
||||
}
|
||||
|
||||
if (!access_ok(VERIFY_READ, src, 1))
|
||||
return -EFAULT;
|
||||
|
||||
n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user,
|
||||
&ptr);
|
||||
if (n != 0)
|
||||
return -EFAULT;
|
||||
return strnlen(dst, count);
|
||||
}
|
||||
EXPORT_SYMBOL(strncpy_from_user);
|
||||
EXPORT_SYMBOL(__strncpy_from_user);
|
||||
|
||||
static int clear_chunk(unsigned long addr, int len, void *unused)
|
||||
{
|
||||
@@ -215,22 +208,16 @@ static int clear_chunk(unsigned long addr, int len, void *unused)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __clear_user(void __user *mem, int len)
|
||||
{
|
||||
return buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL);
|
||||
}
|
||||
|
||||
int clear_user(void __user *mem, int len)
|
||||
unsigned long __clear_user(void __user *mem, unsigned long len)
|
||||
{
|
||||
if (segment_eq(get_fs(), KERNEL_DS)) {
|
||||
memset((__force void*)mem, 0, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return access_ok(VERIFY_WRITE, mem, len) ?
|
||||
buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len;
|
||||
return buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(clear_user);
|
||||
EXPORT_SYMBOL(__clear_user);
|
||||
|
||||
static int strnlen_chunk(unsigned long str, int len, void *arg)
|
||||
{
|
||||
@@ -244,7 +231,7 @@ static int strnlen_chunk(unsigned long str, int len, void *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int strnlen_user(const void __user *str, int len)
|
||||
long __strnlen_user(const void __user *str, long len)
|
||||
{
|
||||
int count = 0, n;
|
||||
|
||||
@@ -256,4 +243,4 @@ int strnlen_user(const void __user *str, int len)
|
||||
return count + 1;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(strnlen_user);
|
||||
EXPORT_SYMBOL(__strnlen_user);
|
||||
|
Reference in New Issue
Block a user