diff options
author | Arnd Bergmann <arnd@arndb.de> | 2022-02-10 18:24:30 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2022-03-28 10:58:45 +0300 |
commit | e65d28d4e9bf90a35ba79c06661a572a38391dec (patch) | |
tree | 6bcaccb91dba8db78710df6afa76856f27b6f968 /arch/csky/include | |
parent | 058d62a03e7d057d5eeec0db800117765ff23e6c (diff) | |
download | linux-e65d28d4e9bf90a35ba79c06661a572a38391dec.tar.xz |
uaccess: fix integer overflow on access_ok()
commit 222ca305c9fd39e5ed8104da25c09b2b79a516a8 upstream.
Three architectures check the end of a user access against the
address limit without taking a possible overflow into account.
Passing a negative length or another overflow in here returns
success when it should not.
Use the most common correct implementation here, which optimizes
for a constant 'size' argument, and turns the common case into a
single comparison.
Cc: stable@vger.kernel.org
Fixes: da551281947c ("csky: User access")
Fixes: f663b60f5215 ("microblaze: Fix uaccess_ok macro")
Fixes: 7567746e1c0d ("Hexagon: Add user access functions")
Reported-by: David Laight <David.Laight@aculab.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch/csky/include')
-rw-r--r-- | arch/csky/include/asm/uaccess.h | 7 |
1 files changed, 3 insertions, 4 deletions
diff --git a/arch/csky/include/asm/uaccess.h b/arch/csky/include/asm/uaccess.h index c40f06ee8d3e..ac5a54f57d40 100644 --- a/arch/csky/include/asm/uaccess.h +++ b/arch/csky/include/asm/uaccess.h @@ -3,14 +3,13 @@ #ifndef __ASM_CSKY_UACCESS_H #define __ASM_CSKY_UACCESS_H -#define user_addr_max() \ - (uaccess_kernel() ? KERNEL_DS.seg : get_fs().seg) +#define user_addr_max() (current_thread_info()->addr_limit.seg) static inline int __access_ok(unsigned long addr, unsigned long size) { - unsigned long limit = current_thread_info()->addr_limit.seg; + unsigned long limit = user_addr_max(); - return ((addr < limit) && ((addr + size) < limit)); + return (size <= limit) && (addr <= (limit - size)); } #define __access_ok __access_ok |