Commit 08382338 authored by Al Viro's avatar Al Viro Committed by Greg Kroah-Hartman

openrisc: fix copy_from_user()

commit acb2505d upstream.

... that should zero on faults.  Also remove the <censored> helpful
logics wrt range truncation copied from ppc32.  Where it had ever
been needed only in case of copy_from_user() *and* had not been merged
into the mainline until a month after the need had disappeared.
A decade before openrisc went into mainline, I might add...
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e3d74efc
...@@ -273,28 +273,20 @@ __copy_tofrom_user(void *to, const void *from, unsigned long size); ...@@ -273,28 +273,20 @@ __copy_tofrom_user(void *to, const void *from, unsigned long size);
static inline unsigned long static inline unsigned long
copy_from_user(void *to, const void *from, unsigned long n) copy_from_user(void *to, const void *from, unsigned long n)
{ {
unsigned long over; unsigned long res = n;
if (access_ok(VERIFY_READ, from, n)) if (likely(access_ok(VERIFY_READ, from, n)))
return __copy_tofrom_user(to, from, n); n = __copy_tofrom_user(to, from, n);
if ((unsigned long)from < TASK_SIZE) { if (unlikely(res))
over = (unsigned long)from + n - TASK_SIZE; memset(to + (n - res), 0, res);
return __copy_tofrom_user(to, from, n - over) + over; return res;
}
return n;
} }
static inline unsigned long static inline unsigned long
copy_to_user(void *to, const void *from, unsigned long n) copy_to_user(void *to, const void *from, unsigned long n)
{ {
unsigned long over; if (likely(access_ok(VERIFY_WRITE, to, n)))
n = __copy_tofrom_user(to, from, n);
if (access_ok(VERIFY_WRITE, to, n))
return __copy_tofrom_user(to, from, n);
if ((unsigned long)to < TASK_SIZE) {
over = (unsigned long)to + n - TASK_SIZE;
return __copy_tofrom_user(to, from, n - over) + over;
}
return n; return n;
} }
...@@ -303,13 +295,8 @@ extern unsigned long __clear_user(void *addr, unsigned long size); ...@@ -303,13 +295,8 @@ extern unsigned long __clear_user(void *addr, unsigned long size);
static inline __must_check unsigned long static inline __must_check unsigned long
clear_user(void *addr, unsigned long size) clear_user(void *addr, unsigned long size)
{ {
if (likely(access_ok(VERIFY_WRITE, addr, size)))
if (access_ok(VERIFY_WRITE, addr, size)) size = __clear_user(addr, size);
return __clear_user(addr, size);
if ((unsigned long)addr < TASK_SIZE) {
unsigned long over = (unsigned long)addr + size - TASK_SIZE;
return __clear_user(addr, size - over) + over;
}
return size; return size;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment