asm-generic: uaccess: remove inline strncpy_from_user/strnlen_user
authorArnd Bergmann <arnd@arndb.de>
Sat, 23 Jan 2021 14:21:22 +0000 (15:21 +0100)
committerArnd Bergmann <arnd@arndb.de>
Tue, 27 Jul 2021 21:01:13 +0000 (23:01 +0200)
The inline version is used on three NOMMU architectures and is
particularly inefficient when it scans the string one byte at a time
twice. It also lacks a check for user_addr_max(), but this is
probably ok on NOMMU targets.

Consolidate the asm-generic implementation with the library version
that is used everywhere else.  This version is generalized enough to
work efficiently on both MMU and NOMMU targets, and using the
same code everywhere reduces the potential for subtle bugs.

Mark the prototypes as __must_check in the process.

Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
arch/h8300/Kconfig
arch/m68k/Kconfig
arch/riscv/Kconfig
include/asm-generic/uaccess.h

index 3e3e0f1..53dfd2d 100644 (file)
@@ -11,6 +11,8 @@ config H8300
        select GENERIC_IRQ_SHOW
        select FRAME_POINTER
        select GENERIC_CPU_DEVICES
+       select GENERIC_STRNCPY_FROM_USER
+       select GENERIC_STRNLEN_USER
        select MODULES_USE_ELF_RELA
        select COMMON_CLK
        select ARCH_WANT_FRAME_POINTERS
index 96989ad..37a65be 100644 (file)
@@ -16,8 +16,8 @@ config M68K
        select GENERIC_CPU_DEVICES
        select GENERIC_IOMAP
        select GENERIC_IRQ_SHOW
-       select GENERIC_STRNCPY_FROM_USER if MMU
-       select GENERIC_STRNLEN_USER if MMU
+       select GENERIC_STRNCPY_FROM_USER
+       select GENERIC_STRNLEN_USER
        select HAVE_AOUT if MMU
        select HAVE_ASM_MODVERSIONS
        select HAVE_DEBUG_BUGVERBOSE
index 8fcceb8..47bbbca 100644 (file)
@@ -56,8 +56,8 @@ config RISCV
        select GENERIC_PTDUMP if MMU
        select GENERIC_SCHED_CLOCK
        select GENERIC_SMP_IDLE_THREAD
-       select GENERIC_STRNCPY_FROM_USER if MMU
-       select GENERIC_STRNLEN_USER if MMU
+       select GENERIC_STRNCPY_FROM_USER
+       select GENERIC_STRNLEN_USER
        select GENERIC_TIME_VSYSCALL if MMU && 64BIT
        select HANDLE_DOMAIN_IRQ
        select HAVE_ARCH_AUDITSYSCALL
index 2f8a5d3..10ffa8b 100644 (file)
@@ -119,6 +119,11 @@ static inline void set_fs(mm_segment_t fs)
 #ifndef uaccess_kernel
 #define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
 #endif
+
+#ifndef user_addr_max
+#define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE)
+#endif
+
 #endif /* CONFIG_SET_FS */
 
 #define access_ok(addr, size) __access_ok((unsigned long)(addr),(size))
@@ -244,44 +249,6 @@ static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
 extern int __get_user_bad(void) __attribute__((noreturn));
 
 /*
- * Copy a null terminated string from userspace.
- */
-#ifndef strncpy_from_user
-static inline long
-strncpy_from_user(char *dst, const char __user *src, long count)
-{
-       char *tmp;
-
-       if (!access_ok(src, 1))
-               return -EFAULT;
-
-       strncpy(dst, (const char __force *)src, count);
-       for (tmp = dst; *tmp && count > 0; tmp++, count--)
-               ;
-       return (tmp - dst);
-}
-#endif
-
-#ifndef strnlen_user
-/*
- * Return the size of a string (including the ending 0)
- *
- * Return 0 on exception, a value greater than N if too long
- *
- * Unlike strnlen, strnlen_user includes the nul terminator in
- * its returned count. Callers should check for a returned value
- * greater than N as an indication the string is too long.
- */
-static inline long strnlen_user(const char __user *src, long n)
-{
-       if (!access_ok(src, 1))
-               return 0;
-
-       return strnlen(src, n) + 1;
-}
-#endif
-
-/*
  * Zero Userspace
  */
 #ifndef __clear_user
@@ -305,4 +272,8 @@ clear_user(void __user *to, unsigned long n)
 
 #include <asm/extable.h>
 
+__must_check long strncpy_from_user(char *dst, const char __user *src,
+                                   long count);
+__must_check long strnlen_user(const char __user *src, long n);
+
 #endif /* __ASM_GENERIC_UACCESS_H */