| From 8926d88ced46700bf6117ceaf391480b943ea9f4 Mon Sep 17 00:00:00 2001 |
| From: Arnd Bergmann <arnd@arndb.de> |
| Date: Mon, 14 Feb 2022 15:48:14 +0100 |
| Subject: nds32: fix access_ok() checks in get/put_user |
| |
| From: Arnd Bergmann <arnd@arndb.de> |
| |
| commit 8926d88ced46700bf6117ceaf391480b943ea9f4 upstream. |
| |
| The get_user()/put_user() functions are meant to check for |
| access_ok(), while the __get_user()/__put_user() functions |
| don't. |
| |
| This broke in 4.19 for nds32, when it gained an extraneous |
| check in __get_user(), but lost the check it needs in |
| __put_user(). |
| |
| Fixes: 487913ab18c2 ("nds32: Extract the checking and getting pointer to a macro") |
| Cc: stable@vger.kernel.org @ v4.19+ |
| Reviewed-by: Christoph Hellwig <hch@lst.de> |
| Signed-off-by: Arnd Bergmann <arnd@arndb.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/nds32/include/asm/uaccess.h | 22 +++++++++++++++++----- |
| 1 file changed, 17 insertions(+), 5 deletions(-) |
| |
| --- a/arch/nds32/include/asm/uaccess.h |
| +++ b/arch/nds32/include/asm/uaccess.h |
| @@ -70,9 +70,7 @@ static inline void set_fs(mm_segment_t f |
| * versions are void (ie, don't return a value as such). |
| */ |
| |
| -#define get_user __get_user \ |
| - |
| -#define __get_user(x, ptr) \ |
| +#define get_user(x, ptr) \ |
| ({ \ |
| long __gu_err = 0; \ |
| __get_user_check((x), (ptr), __gu_err); \ |
| @@ -85,6 +83,14 @@ static inline void set_fs(mm_segment_t f |
| (void)0; \ |
| }) |
| |
| +#define __get_user(x, ptr) \ |
| +({ \ |
| + long __gu_err = 0; \ |
| + const __typeof__(*(ptr)) __user *__p = (ptr); \ |
| + __get_user_err((x), __p, (__gu_err)); \ |
| + __gu_err; \ |
| +}) |
| + |
| #define __get_user_check(x, ptr, err) \ |
| ({ \ |
| const __typeof__(*(ptr)) __user *__p = (ptr); \ |
| @@ -165,12 +171,18 @@ do { \ |
| : "r"(addr), "i"(-EFAULT) \ |
| : "cc") |
| |
| -#define put_user __put_user \ |
| +#define put_user(x, ptr) \ |
| +({ \ |
| + long __pu_err = 0; \ |
| + __put_user_check((x), (ptr), __pu_err); \ |
| + __pu_err; \ |
| +}) |
| |
| #define __put_user(x, ptr) \ |
| ({ \ |
| long __pu_err = 0; \ |
| - __put_user_err((x), (ptr), __pu_err); \ |
| + __typeof__(*(ptr)) __user *__p = (ptr); \ |
| + __put_user_err((x), __p, __pu_err); \ |
| __pu_err; \ |
| }) |
| |