diff options
author | Arnd Bergmann <arnd@arndb.de> | 2022-02-10 16:24:30 +0100 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2022-02-14 22:30:53 +0100 |
commit | 222ca305c9fd39e5ed8104da25c09b2b79a516a8 (patch) | |
tree | 226513c6b142c9fab9582d776f77d00e2cbee47c /arch/hexagon | |
parent | dfd42facf1e4ada021b939b4e19c935dcdd55566 (diff) | |
download | linux-222ca305c9fd39e5ed8104da25c09b2b79a516a8.tar.gz linux-222ca305c9fd39e5ed8104da25c09b2b79a516a8.tar.bz2 linux-222ca305c9fd39e5ed8104da25c09b2b79a516a8.zip |
uaccess: fix integer overflow on access_ok()
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>
Diffstat (limited to 'arch/hexagon')
-rw-r--r-- | arch/hexagon/include/asm/uaccess.h | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/arch/hexagon/include/asm/uaccess.h b/arch/hexagon/include/asm/uaccess.h index ef5bfef8d490..719ba3f3c45c 100644 --- a/arch/hexagon/include/asm/uaccess.h +++ b/arch/hexagon/include/asm/uaccess.h @@ -25,17 +25,17 @@ * Returns true (nonzero) if the memory block *may* be valid, false (zero) * if it is definitely invalid. * - * User address space in Hexagon, like x86, goes to 0xbfffffff, so the - * simple MSB-based tests used by MIPS won't work. Some further - * optimization is probably possible here, but for now, keep it - * reasonably simple and not *too* slow. After all, we've got the - * MMU for backup. */ +#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) +#define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE) -#define __access_ok(addr, size) \ - ((get_fs().seg == KERNEL_DS.seg) || \ - (((unsigned long)addr < get_fs().seg) && \ - (unsigned long)size < (get_fs().seg - (unsigned long)addr))) +static inline int __access_ok(unsigned long addr, unsigned long size) +{ + unsigned long limit = TASK_SIZE; + + return (size <= limit) && (addr <= (limit - size)); +} +#define __access_ok __access_ok /* * When a kernel-mode page fault is taken, the faulting instruction |