aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/lib/uaccess_pt.c34
-rw-r--r--arch/s390/lib/uaccess_std.c46
2 files changed, 34 insertions, 46 deletions
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index c1aaf22c326b..304e07086ab3 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -202,27 +202,29 @@ fault:
202static size_t strncpy_from_user_pt(size_t count, const char __user *src, 202static size_t strncpy_from_user_pt(size_t count, const char __user *src,
203 char *dst) 203 char *dst)
204{ 204{
205 size_t n = strnlen_user_pt(count, src); 205 size_t done, len, offset, len_str;
206 206
207 if (unlikely(!count)) 207 if (unlikely(!count))
208 return 0; 208 return 0;
209 if (!n)
210 return -EFAULT;
211 if (n > count)
212 n = count;
213 if (segment_eq(get_fs(), KERNEL_DS)) { 209 if (segment_eq(get_fs(), KERNEL_DS)) {
214 memcpy(dst, (const char __kernel __force *) src, n); 210 len = strnlen((const char __kernel __force *) src, count) + 1;
215 if (dst[n-1] == '\0') 211 if (len > count)
216 return n-1; 212 len = count;
217 else 213 memcpy(dst, (const char __kernel __force *) src, len);
218 return n; 214 return (dst[len - 1] == '\0') ? len - 1 : len;
219 } 215 }
220 if (__user_copy_pt((unsigned long) src, dst, n, 0)) 216 done = 0;
221 return -EFAULT; 217 do {
222 if (dst[n-1] == '\0') 218 offset = (size_t)src & ~PAGE_MASK;
223 return n-1; 219 len = min(count - done, PAGE_SIZE - offset);
224 else 220 if (__user_copy_pt((unsigned long) src, dst, len, 0))
225 return n; 221 return -EFAULT;
222 len_str = strnlen(dst, len);
223 done += len_str;
224 src += len_str;
225 dst += len_str;
226 } while ((len_str == len) && (done < count));
227 return done;
226} 228}
227 229
228static size_t copy_in_user_pt(size_t n, void __user *to, 230static size_t copy_in_user_pt(size_t n, void __user *to,
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
index 79c6c7d76e08..4a75d475b06a 100644
--- a/arch/s390/lib/uaccess_std.c
+++ b/arch/s390/lib/uaccess_std.c
@@ -206,38 +206,24 @@ size_t strnlen_user_std(size_t size, const char __user *src)
206 return size; 206 return size;
207} 207}
208 208
209size_t strncpy_from_user_std(size_t size, const char __user *src, char *dst) 209size_t strncpy_from_user_std(size_t count, const char __user *src, char *dst)
210{ 210{
211 register unsigned long reg0 asm("0") = 0UL; 211 size_t done, len, offset, len_str;
212 unsigned long tmp1, tmp2;
213 212
214 asm volatile( 213 if (unlikely(!count))
215 " la %3,0(%1)\n" 214 return 0;
216 " la %4,0(%0,%1)\n" 215 done = 0;
217 " sacf 256\n" 216 do {
218 "0: srst %4,%3\n" 217 offset = (size_t)src & ~PAGE_MASK;
219 " jo 0b\n" 218 len = min(count - done, PAGE_SIZE - offset);
220 " sacf 0\n" 219 if (copy_from_user_std(len, src, dst))
221 " la %0,0(%4)\n" 220 return -EFAULT;
222 " jh 1f\n" /* found \0 in string ? */ 221 len_str = strnlen(dst, len);
223 " "AHI" %4,1\n" /* include \0 in copy */ 222 done += len_str;
224 "1:"SLR" %0,%1\n" /* %0 = return length (without \0) */ 223 src += len_str;
225 " "SLR" %4,%1\n" /* %4 = copy length (including \0) */ 224 dst += len_str;
226 "2: mvcp 0(%4,%2),0(%1),%5\n" 225 } while ((len_str == len) && (done < count));
227 " jz 9f\n" 226 return done;
228 "3:"AHI" %4,-256\n"
229 " la %1,256(%1)\n"
230 " la %2,256(%2)\n"
231 "4: mvcp 0(%4,%2),0(%1),%5\n"
232 " jnz 3b\n"
233 " j 9f\n"
234 "7: sacf 0\n"
235 "8:"LHI" %0,%6\n"
236 "9:\n"
237 EX_TABLE(0b,7b) EX_TABLE(2b,8b) EX_TABLE(4b,8b)
238 : "+a" (size), "+a" (src), "+d" (dst), "=a" (tmp1), "=a" (tmp2)
239 : "d" (reg0), "K" (-EFAULT) : "cc", "memory");
240 return size;
241} 227}
242 228
243#define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg) \ 229#define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg) \