Commit e93a1cb8 authored by Heiko Carstens's avatar Heiko Carstens Committed by Arnd Bergmann
Browse files

s390: use generic strncpy/strnlen from_user



The s390 variant of strncpy_from_user() is slightly faster than the
generic variant, however convert to the generic variant now to follow
most if not all other architectures.

Converting to the generic variant was already considered a couple of
years ago. See commit f5c8b960 ("s390/uaccess: use sane length for
__strncpy_from_user()").

Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parent b26b1816
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -130,6 +130,8 @@ config S390
	select GENERIC_GETTIMEOFDAY
	select GENERIC_PTDUMP
	select GENERIC_SMP_IDLE_THREAD
	select GENERIC_STRNCPY_FROM_USER
	select GENERIC_STRNLEN_USER
	select GENERIC_TIME_VSYSCALL
	select GENERIC_VDSO_TIME_NS
	select HAVE_ALIGNED_STRUCT_PAGE if SLUB
+2 −16
Original line number Diff line number Diff line
@@ -233,23 +233,9 @@ raw_copy_in_user(void __user *to, const void __user *from, unsigned long n);
/*
 * Copy a null terminated string from userspace.
 */
long __must_check strncpy_from_user(char *dst, const char __user *src, long count);

long __strncpy_from_user(char *dst, const char __user *src, long count);

static inline long __must_check
strncpy_from_user(char *dst, const char __user *src, long count)
{
	might_fault();
	return __strncpy_from_user(dst, src, count);
}

unsigned long __must_check __strnlen_user(const char __user *src, unsigned long count);

static inline unsigned long strnlen_user(const char __user *src, unsigned long n)
{
	might_fault();
	return __strnlen_user(src, n);
}
long __must_check strnlen_user(const char __user *src, long count);

/*
 * Zero Userspace
+0 −52
Original line number Diff line number Diff line
@@ -338,55 +338,3 @@ unsigned long __clear_user(void __user *to, unsigned long size)
	return clear_user_xc(to, size);
}
EXPORT_SYMBOL(__clear_user);

static inline unsigned long strnlen_user_srst(const char __user *src,
					      unsigned long size)
{
	unsigned long tmp1, tmp2;

	asm volatile(
		"   lghi  0,0\n"
		"   la    %2,0(%1)\n"
		"   la    %3,0(%0,%1)\n"
		"   slgr  %0,%0\n"
		"   sacf  256\n"
		"0: srst  %3,%2\n"
		"   jo    0b\n"
		"   la    %0,1(%3)\n"	/* strnlen_user results includes \0 */
		"   slgr  %0,%1\n"
		"1: sacf  768\n"
		EX_TABLE(0b,1b)
		: "+a" (size), "+a" (src), "=a" (tmp1), "=a" (tmp2)
		:
		: "cc", "memory", "0");
	return size;
}

unsigned long __strnlen_user(const char __user *src, unsigned long size)
{
	if (unlikely(!size))
		return 0;
	return strnlen_user_srst(src, size);
}
EXPORT_SYMBOL(__strnlen_user);

long __strncpy_from_user(char *dst, const char __user *src, long size)
{
	size_t done, len, offset, len_str;

	if (unlikely(size <= 0))
		return 0;
	done = 0;
	do {
		offset = (size_t)src & (L1_CACHE_BYTES - 1);
		len = min(size - done, L1_CACHE_BYTES - offset);
		if (copy_from_user(dst, src, len))
			return -EFAULT;
		len_str = strnlen(dst, len);
		done += len_str;
		src += len_str;
		dst += len_str;
	} while ((len_str == len) && (done < size));
	return done;
}
EXPORT_SYMBOL(__strncpy_from_user);