* [PATCH v2 01/18] uaccess: fix integer overflow on access_ok()
[not found] <20220216131332.1489939-1-arnd@kernel.org>
@ 2022-02-16 13:13 ` Arnd Bergmann
2022-02-16 13:13 ` [PATCH v2 03/18] nds32: fix access_ok() checks in get/put_user Arnd Bergmann
1 sibling, 0 replies; 3+ messages in thread
From: Arnd Bergmann @ 2022-02-16 13:13 UTC (permalink / raw)
To: Linus Torvalds, Christoph Hellwig, linux-arch, linux-mm,
linux-api, arnd, linux-kernel, viro
Cc: linux, will, guoren, bcain, geert, monstr, tsbogend, nickhu,
green.hu, dinguyen, shorne, deller, mpe, peterz, mingo,
mark.rutland, hca, dalias, davem, richard, x86, jcmvbkbc,
ebiederm, akpm, ardb, linux-alpha, linux-snps-arc, linux-csky,
linux-hexagon, linux-ia64, linux-m68k, linux-mips, openrisc,
linux-parisc, linuxppc-dev, linux-riscv, linux-s390, linux-sh,
sparclinux, linux-um, linux-xtensa, stable, David Laight
From: Arnd Bergmann <arnd@arndb.de>
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>
---
arch/csky/include/asm/uaccess.h | 7 +++----
arch/hexagon/include/asm/uaccess.h | 18 +++++++++---------
arch/microblaze/include/asm/uaccess.h | 19 ++++---------------
3 files changed, 16 insertions(+), 28 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
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
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h
index d2a8ef9f8978..5b6e0e7788f4 100644
--- a/arch/microblaze/include/asm/uaccess.h
+++ b/arch/microblaze/include/asm/uaccess.h
@@ -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"
--
2.29.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH v2 03/18] nds32: fix access_ok() checks in get/put_user
[not found] <20220216131332.1489939-1-arnd@kernel.org>
2022-02-16 13:13 ` [PATCH v2 01/18] uaccess: fix integer overflow on access_ok() Arnd Bergmann
@ 2022-02-16 13:13 ` Arnd Bergmann
2022-02-18 6:25 ` Christoph Hellwig
1 sibling, 1 reply; 3+ messages in thread
From: Arnd Bergmann @ 2022-02-16 13:13 UTC (permalink / raw)
To: Linus Torvalds, Christoph Hellwig, linux-arch, linux-mm,
linux-api, arnd, linux-kernel, viro
Cc: linux, will, guoren, bcain, geert, monstr, tsbogend, nickhu,
green.hu, dinguyen, shorne, deller, mpe, peterz, mingo,
mark.rutland, hca, dalias, davem, richard, x86, jcmvbkbc,
ebiederm, akpm, ardb, linux-alpha, linux-snps-arc, linux-csky,
linux-hexagon, linux-ia64, linux-m68k, linux-mips, openrisc,
linux-parisc, linuxppc-dev, linux-riscv, linux-s390, linux-sh,
sparclinux, linux-um, linux-xtensa, stable
From: Arnd Bergmann <arnd@arndb.de>
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+
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/nds32/include/asm/uaccess.h | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/arch/nds32/include/asm/uaccess.h b/arch/nds32/include/asm/uaccess.h
index d4cbf069dc22..37a40981deb3 100644
--- 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 fs)
* 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 fs)
(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; \
})
--
2.29.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v2 03/18] nds32: fix access_ok() checks in get/put_user
2022-02-16 13:13 ` [PATCH v2 03/18] nds32: fix access_ok() checks in get/put_user Arnd Bergmann
@ 2022-02-18 6:25 ` Christoph Hellwig
0 siblings, 0 replies; 3+ messages in thread
From: Christoph Hellwig @ 2022-02-18 6:25 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Linus Torvalds, Christoph Hellwig, linux-arch, linux-mm,
linux-api, arnd, linux-kernel, viro, linux, will, guoren, bcain,
geert, monstr, tsbogend, nickhu, green.hu, dinguyen, shorne,
deller, mpe, peterz, mingo, mark.rutland, hca, dalias, davem,
richard, x86, jcmvbkbc, ebiederm, akpm, ardb, linux-alpha,
linux-snps-arc, linux-csky, linux-hexagon, linux-ia64, linux-m68k,
linux-mips, openrisc, linux-parisc, linuxppc-dev, linux-riscv,
linux-s390, linux-sh, sparclinux, linux-um, linux-xtensa, stable
On Wed, Feb 16, 2022 at 02:13:17PM +0100, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> 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().
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2022-02-18 6:25 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20220216131332.1489939-1-arnd@kernel.org>
2022-02-16 13:13 ` [PATCH v2 01/18] uaccess: fix integer overflow on access_ok() Arnd Bergmann
2022-02-16 13:13 ` [PATCH v2 03/18] nds32: fix access_ok() checks in get/put_user Arnd Bergmann
2022-02-18 6:25 ` Christoph Hellwig
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).