Commit 98b861a3 authored by Arnd Bergmann's avatar Arnd Bergmann

asm-generic: uaccess: remove inline strncpy_from_user/strnlen_user

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: default avatarGeert Uytterhoeven <geert@linux-m68k.org>
Acked-by: default avatarGeert Uytterhoeven <geert@linux-m68k.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parent e93a1cb8
...@@ -11,6 +11,8 @@ config H8300 ...@@ -11,6 +11,8 @@ config H8300
select GENERIC_IRQ_SHOW select GENERIC_IRQ_SHOW
select FRAME_POINTER select FRAME_POINTER
select GENERIC_CPU_DEVICES select GENERIC_CPU_DEVICES
select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER
select MODULES_USE_ELF_RELA select MODULES_USE_ELF_RELA
select COMMON_CLK select COMMON_CLK
select ARCH_WANT_FRAME_POINTERS select ARCH_WANT_FRAME_POINTERS
......
...@@ -16,8 +16,8 @@ config M68K ...@@ -16,8 +16,8 @@ config M68K
select GENERIC_CPU_DEVICES select GENERIC_CPU_DEVICES
select GENERIC_IOMAP select GENERIC_IOMAP
select GENERIC_IRQ_SHOW select GENERIC_IRQ_SHOW
select GENERIC_STRNCPY_FROM_USER if MMU select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER if MMU select GENERIC_STRNLEN_USER
select HAVE_AOUT if MMU select HAVE_AOUT if MMU
select HAVE_ASM_MODVERSIONS select HAVE_ASM_MODVERSIONS
select HAVE_DEBUG_BUGVERBOSE select HAVE_DEBUG_BUGVERBOSE
......
...@@ -56,8 +56,8 @@ config RISCV ...@@ -56,8 +56,8 @@ config RISCV
select GENERIC_PTDUMP if MMU select GENERIC_PTDUMP if MMU
select GENERIC_SCHED_CLOCK select GENERIC_SCHED_CLOCK
select GENERIC_SMP_IDLE_THREAD select GENERIC_SMP_IDLE_THREAD
select GENERIC_STRNCPY_FROM_USER if MMU select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER if MMU select GENERIC_STRNLEN_USER
select GENERIC_TIME_VSYSCALL if MMU && 64BIT select GENERIC_TIME_VSYSCALL if MMU && 64BIT
select HANDLE_DOMAIN_IRQ select HANDLE_DOMAIN_IRQ
select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_AUDITSYSCALL
......
...@@ -119,6 +119,11 @@ static inline void set_fs(mm_segment_t fs) ...@@ -119,6 +119,11 @@ static inline void set_fs(mm_segment_t fs)
#ifndef uaccess_kernel #ifndef uaccess_kernel
#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) #define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
#endif #endif
#ifndef user_addr_max
#define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE)
#endif
#endif /* CONFIG_SET_FS */ #endif /* CONFIG_SET_FS */
#define access_ok(addr, size) __access_ok((unsigned long)(addr),(size)) #define access_ok(addr, size) __access_ok((unsigned long)(addr),(size))
...@@ -243,44 +248,6 @@ static inline int __get_user_fn(size_t size, const void __user *ptr, void *x) ...@@ -243,44 +248,6 @@ static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
extern int __get_user_bad(void) __attribute__((noreturn)); 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 * Zero Userspace
*/ */
...@@ -305,4 +272,8 @@ clear_user(void __user *to, unsigned long n) ...@@ -305,4 +272,8 @@ clear_user(void __user *to, unsigned long n)
#include <asm/extable.h> #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 */ #endif /* __ASM_GENERIC_UACCESS_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment