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:da55128194("csky: User access") Fixes:f663b60f52("microblaze: Fix uaccess_ok macro") Fixes:7567746e1c("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>
This commit is contained in:
@@ -39,24 +39,13 @@
|
||||
|
||||
# define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
|
||||
|
||||
static inline int access_ok(const void __user *addr, unsigned long size)
|
||||
static inline int __access_ok(unsigned long addr, unsigned long size)
|
||||
{
|
||||
if (!size)
|
||||
goto ok;
|
||||
unsigned long limit = user_addr_max();
|
||||
|
||||
if ((get_fs().seg < ((unsigned long)addr)) ||
|
||||
(get_fs().seg < ((unsigned long)addr + size - 1))) {
|
||||
pr_devel("ACCESS fail at 0x%08x (size 0x%x), seg 0x%08x\n",
|
||||
(__force u32)addr, (u32)size,
|
||||
(u32)get_fs().seg);
|
||||
return 0;
|
||||
}
|
||||
ok:
|
||||
pr_devel("ACCESS OK at 0x%08x (size 0x%x), seg 0x%08x\n",
|
||||
(__force u32)addr, (u32)size,
|
||||
(u32)get_fs().seg);
|
||||
return 1;
|
||||
return (size <= limit) && (addr <= (limit - size));
|
||||
}
|
||||
#define access_ok(addr, size) __access_ok((unsigned long)addr, size)
|
||||
|
||||
# define __FIXUP_SECTION ".section .fixup,\"ax\"\n"
|
||||
# define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n"
|
||||
|
||||
Reference in New Issue
Block a user