ppc32: fix copy_from_user()
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 21 Aug 2016 23:16:26 +0000 (19:16 -0400)
committerBen Hutchings <ben@decadent.org.uk>
Sun, 20 Nov 2016 01:01:39 +0000 (01:01 +0000)
commit 224264657b8b228f949b42346e09ed8c90136a8e upstream.

should clear on access_ok() failures.  Also remove the useless
range truncation logics.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
[bwh: Backported to 3.2: no calls to check_object_size()]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
arch/powerpc/include/asm/uaccess.h

index bd0fb84..4d4a30c 100644 (file)
@@ -332,30 +332,17 @@ extern unsigned long __copy_tofrom_user(void __user *to,
 static inline unsigned long copy_from_user(void *to,
                const void __user *from, unsigned long n)
 {
-       unsigned long over;
-
-       if (access_ok(VERIFY_READ, from, n))
+       if (likely(access_ok(VERIFY_READ, from, n)))
                return __copy_tofrom_user((__force void __user *)to, from, n);
-       if ((unsigned long)from < TASK_SIZE) {
-               over = (unsigned long)from + n - TASK_SIZE;
-               return __copy_tofrom_user((__force void __user *)to, from,
-                               n - over) + over;
-       }
+       memset(to, 0, n);
        return n;
 }
 
 static inline unsigned long copy_to_user(void __user *to,
                const void *from, unsigned long n)
 {
-       unsigned long over;
-
        if (access_ok(VERIFY_WRITE, to, n))
                return __copy_tofrom_user(to, (__force void __user *)from, n);
-       if ((unsigned long)to < TASK_SIZE) {
-               over = (unsigned long)to + n - TASK_SIZE;
-               return __copy_tofrom_user(to, (__force void __user *)from,
-                               n - over) + over;
-       }
        return n;
 }
 
@@ -446,10 +433,6 @@ static inline unsigned long clear_user(void __user *addr, unsigned long size)
        might_sleep();
        if (likely(access_ok(VERIFY_WRITE, 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;
 }