On Thu, Jul 22, 2021 at 04:01:39PM +0200, Arnd Bergmann wrote: > On Thu, Jul 22, 2021 at 3:57 PM Johannes Berg <johannes@xxxxxxxxxxxxxxxx> wrote: > > > > > > > > The remaining architectures at the moment are: ia64, mips, parisc, > > > s390, um and xtensa. We should probably convert these as well, but > > > > I'm not sure it makes sense to convert um, the implementation uses > > strncpy(), and that should use the libc implementation, which is tuned > > for the actual hardware that the binary is running on, so performance > > wise that might be better. > > > > OTOH, maybe this is all in the noise given the huge syscall overhead in > > um, so maybe unifying it would make more sense. > > Right, makes sense. I suppose if we end up converting mips and s390, > we should just do arch/um and the others as well for consistency, even > if that adds some overhead. Feel free to add the s390 patch below on top of your series. However one question: the strncpy_from_user() prototype now comes everywhere without the __must_check attribute. Is there any reason for that? At least for s390 I want to keep that. >From 03ad679909af58e1dc6864f47ce67210f0534c39 Mon Sep 17 00:00:00 2001 From: Heiko Carstens <hca@xxxxxxxxxxxxx> Date: Thu, 22 Jul 2021 21:48:18 +0200 Subject: [PATCH] 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 f5c8b9601036 ("s390/uaccess: use sane length for __strncpy_from_user()"). Signed-off-by: Heiko Carstens <hca@xxxxxxxxxxxxx> --- arch/s390/Kconfig | 2 -- arch/s390/include/asm/uaccess.h | 18 ++---------- arch/s390/lib/uaccess.c | 52 --------------------------------- 3 files changed, 2 insertions(+), 70 deletions(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index f4f39087cad0..a0e2130f0100 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -75,8 +75,6 @@ config S390 select ARCH_HAS_SET_MEMORY select ARCH_HAS_STRICT_KERNEL_RWX select ARCH_HAS_STRICT_MODULE_RWX - select ARCH_HAS_STRNCPY_FROM_USER - select ARCH_HAS_STRNLEN_USER select ARCH_HAS_SYSCALL_WRAPPER select ARCH_HAS_UBSAN_SANITIZE_ALL select ARCH_HAS_VDSO_DATA diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index 2316f2440881..9ed9aa37e836 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h @@ -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 diff --git a/arch/s390/lib/uaccess.c b/arch/s390/lib/uaccess.c index 7ec8b1fa0f08..94ca99bde59d 100644 --- a/arch/s390/lib/uaccess.c +++ b/arch/s390/lib/uaccess.c @@ -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); -- 2.25.1