Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9fd4470f authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Use the new batched user accesses in generic user string handling



This converts the generic user string functions to use the batched user
access functions.

It makes a big difference on Skylake, which is the first x86
microarchitecture to implement SMAP.  The STAC/CLAC instructions are not
very fast, and doing them for each access inside the loop that copies
strings from user space (which is what the pathname handling does for
every pathname the kernel uses, for example) is very inefficient.

Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 5b24a7a2
Loading
Loading
Loading
Loading
+8 −3
Original line number Original line Diff line number Diff line
@@ -39,7 +39,7 @@ static inline long do_strncpy_from_user(char *dst, const char __user *src, long
		unsigned long c, data;
		unsigned long c, data;


		/* Fall back to byte-at-a-time if we get a page fault */
		/* Fall back to byte-at-a-time if we get a page fault */
		if (unlikely(__get_user(c,(unsigned long __user *)(src+res))))
		if (unlikely(unsafe_get_user(c,(unsigned long __user *)(src+res))))
			break;
			break;
		*(unsigned long *)(dst+res) = c;
		*(unsigned long *)(dst+res) = c;
		if (has_zero(c, &data, &constants)) {
		if (has_zero(c, &data, &constants)) {
@@ -55,7 +55,7 @@ static inline long do_strncpy_from_user(char *dst, const char __user *src, long
	while (max) {
	while (max) {
		char c;
		char c;


		if (unlikely(__get_user(c,src+res)))
		if (unlikely(unsafe_get_user(c,src+res)))
			return -EFAULT;
			return -EFAULT;
		dst[res] = c;
		dst[res] = c;
		if (!c)
		if (!c)
@@ -107,7 +107,12 @@ long strncpy_from_user(char *dst, const char __user *src, long count)
	src_addr = (unsigned long)src;
	src_addr = (unsigned long)src;
	if (likely(src_addr < max_addr)) {
	if (likely(src_addr < max_addr)) {
		unsigned long max = max_addr - src_addr;
		unsigned long max = max_addr - src_addr;
		return do_strncpy_from_user(dst, src, count, max);
		long retval;

		user_access_begin();
		retval = do_strncpy_from_user(dst, src, count, max);
		user_access_end();
		return retval;
	}
	}
	return -EFAULT;
	return -EFAULT;
}
}
+14 −4
Original line number Original line Diff line number Diff line
@@ -45,7 +45,7 @@ static inline long do_strnlen_user(const char __user *src, unsigned long count,
	src -= align;
	src -= align;
	max += align;
	max += align;


	if (unlikely(__get_user(c,(unsigned long __user *)src)))
	if (unlikely(unsafe_get_user(c,(unsigned long __user *)src)))
		return 0;
		return 0;
	c |= aligned_byte_mask(align);
	c |= aligned_byte_mask(align);


@@ -61,7 +61,7 @@ static inline long do_strnlen_user(const char __user *src, unsigned long count,
		if (unlikely(max <= sizeof(unsigned long)))
		if (unlikely(max <= sizeof(unsigned long)))
			break;
			break;
		max -= sizeof(unsigned long);
		max -= sizeof(unsigned long);
		if (unlikely(__get_user(c,(unsigned long __user *)(src+res))))
		if (unlikely(unsafe_get_user(c,(unsigned long __user *)(src+res))))
			return 0;
			return 0;
	}
	}
	res -= align;
	res -= align;
@@ -112,7 +112,12 @@ long strnlen_user(const char __user *str, long count)
	src_addr = (unsigned long)str;
	src_addr = (unsigned long)str;
	if (likely(src_addr < max_addr)) {
	if (likely(src_addr < max_addr)) {
		unsigned long max = max_addr - src_addr;
		unsigned long max = max_addr - src_addr;
		return do_strnlen_user(str, count, max);
		long retval;

		user_access_begin();
		retval = do_strnlen_user(str, count, max);
		user_access_end();
		return retval;
	}
	}
	return 0;
	return 0;
}
}
@@ -141,7 +146,12 @@ long strlen_user(const char __user *str)
	src_addr = (unsigned long)str;
	src_addr = (unsigned long)str;
	if (likely(src_addr < max_addr)) {
	if (likely(src_addr < max_addr)) {
		unsigned long max = max_addr - src_addr;
		unsigned long max = max_addr - src_addr;
		return do_strnlen_user(str, ~0ul, max);
		long retval;

		user_access_begin();
		retval = do_strnlen_user(str, ~0ul, max);
		user_access_end();
		return retval;
	}
	}
	return 0;
	return 0;
}
}