Skip to content

Commit ea2e77f

Browse files
torvaldsAlex Shi
authored andcommitted
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: Linus Torvalds <torvalds@linux-foundation.org> (cherry picked from commit 9fd4470ff4974c41b1db43c3b355b9085af9c12a) Signed-off-by: Alex Shi <alex.shi@linaro.org>
1 parent 798522d commit ea2e77f

2 files changed

Lines changed: 22 additions & 7 deletions

File tree

lib/strncpy_from_user.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ static inline long do_strncpy_from_user(char *dst, const char __user *src, long
3939
unsigned long c, data;
4040

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

58-
if (unlikely(__get_user(c,src+res)))
58+
if (unlikely(unsafe_get_user(c,src+res)))
5959
return -EFAULT;
6060
dst[res] = c;
6161
if (!c)
@@ -107,7 +107,12 @@ long strncpy_from_user(char *dst, const char __user *src, long count)
107107
src_addr = (unsigned long)src;
108108
if (likely(src_addr < max_addr)) {
109109
unsigned long max = max_addr - src_addr;
110-
return do_strncpy_from_user(dst, src, count, max);
110+
long retval;
111+
112+
user_access_begin();
113+
retval = do_strncpy_from_user(dst, src, count, max);
114+
user_access_end();
115+
return retval;
111116
}
112117
return -EFAULT;
113118
}

lib/strnlen_user.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ static inline long do_strnlen_user(const char __user *src, unsigned long count,
4545
src -= align;
4646
max += align;
4747

48-
if (unlikely(__get_user(c,(unsigned long __user *)src)))
48+
if (unlikely(unsafe_get_user(c,(unsigned long __user *)src)))
4949
return 0;
5050
c |= aligned_byte_mask(align);
5151

@@ -61,7 +61,7 @@ static inline long do_strnlen_user(const char __user *src, unsigned long count,
6161
if (unlikely(max <= sizeof(unsigned long)))
6262
break;
6363
max -= sizeof(unsigned long);
64-
if (unlikely(__get_user(c,(unsigned long __user *)(src+res))))
64+
if (unlikely(unsafe_get_user(c,(unsigned long __user *)(src+res))))
6565
return 0;
6666
}
6767
res -= align;
@@ -112,7 +112,12 @@ long strnlen_user(const char __user *str, long count)
112112
src_addr = (unsigned long)str;
113113
if (likely(src_addr < max_addr)) {
114114
unsigned long max = max_addr - src_addr;
115-
return do_strnlen_user(str, count, max);
115+
long retval;
116+
117+
user_access_begin();
118+
retval = do_strnlen_user(str, count, max);
119+
user_access_end();
120+
return retval;
116121
}
117122
return 0;
118123
}
@@ -141,7 +146,12 @@ long strlen_user(const char __user *str)
141146
src_addr = (unsigned long)str;
142147
if (likely(src_addr < max_addr)) {
143148
unsigned long max = max_addr - src_addr;
144-
return do_strnlen_user(str, ~0ul, max);
149+
long retval;
150+
151+
user_access_begin();
152+
retval = do_strnlen_user(str, ~0ul, max);
153+
user_access_end();
154+
return retval;
145155
}
146156
return 0;
147157
}

0 commit comments

Comments
 (0)