]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
m68knommu: fix memcpy() out of bounds warning in get_user()
authorGreg Ungerer <gerg@linux-m68k.org>
Fri, 17 Jan 2020 06:28:19 +0000 (16:28 +1000)
committerGreg Ungerer <gerg@linux-m68k.org>
Mon, 3 Feb 2020 04:43:35 +0000 (14:43 +1000)
Newer versions of gcc are giving warnings in the non-MMU m68k version
of the get_user() macro:

    ./arch/m68k/include/asm/string.h:72:25: warning: ‘__builtin_memcpy’ forming offset [3, 4] is out of the bounds [0, 2] of object ‘__gu_val’ with type ‘short unsigned int’ [-Warray-bounds]

The warnings are generated when smaller sized variables are used as the
result of user space pointers to larger values. For example a
short/2-byte variable stores the result of a user space int (4-byte)
pointer. The warning is in the 8-byte branch of get_user() - even
though that branch is not the taken branch in the warning cases.

Refactor the 8-byte branch of get_user() so that it uses a correctly
formed union type to read and write the source and destination objects.
Keep using the memcpy() just in case the user space pointer is not
naturaly aligned (not required for ColdFire, but needed for early
68000).

Signed-off-by: Greg Ungerer <gerg@linux-m68k.org>
arch/m68k/include/asm/uaccess_no.h

index 0134008bf539b8fc8f0c1a46b20052eca638b7be..6bc80c35726dfbcaf4bc4d2f855f01b31eee99a5 100644 (file)
@@ -71,26 +71,29 @@ extern int __put_user_bad(void);
 #define get_user(x, ptr)                                       \
 ({                                                             \
     int __gu_err = 0;                                          \
-    typeof(x) __gu_val = 0;                                    \
     switch (sizeof(*(ptr))) {                                  \
     case 1:                                                    \
-       __get_user_asm(__gu_err, __gu_val, ptr, b, "=d");       \
+       __get_user_asm(__gu_err, x, ptr, b, "=d");              \
        break;                                                  \
     case 2:                                                    \
-       __get_user_asm(__gu_err, __gu_val, ptr, w, "=r");       \
+       __get_user_asm(__gu_err, x, ptr, w, "=r");              \
        break;                                                  \
     case 4:                                                    \
-       __get_user_asm(__gu_err, __gu_val, ptr, l, "=r");       \
+       __get_user_asm(__gu_err, x, ptr, l, "=r");              \
        break;                                                  \
-    case 8:                                                    \
-       memcpy((void *) &__gu_val, ptr, sizeof (*(ptr)));       \
+    case 8: {                                                  \
+       union {                                                 \
+           u64 l;                                              \
+           __typeof__(*(ptr)) t;                               \
+       } __gu_val;                                             \
+       memcpy(&__gu_val.l, ptr, sizeof(__gu_val.l));           \
+       (x) = __gu_val.t;                                       \
        break;                                                  \
+    }                                                          \
     default:                                                   \
-       __gu_val = 0;                                           \
        __gu_err = __get_user_bad();                            \
        break;                                                  \
     }                                                          \
-    (x) = (typeof(*(ptr))) __gu_val;                           \
     __gu_err;                                                  \
 })
 #define __get_user(x, ptr) get_user(x, ptr)