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: 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>
This commit is contained in:
Arnd Bergmann 2021-01-23 15:21:22 +01:00
parent e93a1cb8d2
commit 98b861a304
4 changed files with 15 additions and 42 deletions

View 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

View 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

View 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

View 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))
@ -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));
/*
* 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
*/
@ -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 */