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

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
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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
+2 −2
Original line number Diff line number Diff line
@@ -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
+2 −2
Original line number Diff line number Diff line
@@ -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
+9 −38
Original line number Diff line number Diff line
@@ -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 */