@@ -661,6 +661,9 @@ __arc_strncpy_from_user(char *dst, const char __user *src, long count)
long res = 0;
char val;
+ if (!access_ok(src, 1))
+ return -EFAULT;
+
if (count == 0)
return 0;
@@ -693,6 +696,9 @@ static inline long __arc_strnlen_user(const char __user *s, long n)
long res, tmp1, cnt;
char val;
+ if (!access_ok(s, 1))
+ return 0;
+
__asm__ __volatile__(
" mov %2, %1 \n"
"1: ldb.ab %3, [%0, 1] \n"
@@ -724,8 +730,8 @@ static inline long __arc_strnlen_user(const char __user *s, long n)
#define INLINE_COPY_FROM_USER
#define __clear_user(d, n) __arc_clear_user(d, n)
-#define __strncpy_from_user(d, s, n) __arc_strncpy_from_user(d, s, n)
-#define __strnlen_user(s, n) __arc_strnlen_user(s, n)
+#define strncpy_from_user(d, s, n) __arc_strncpy_from_user(d, s, n)
+#define strnlen_user(s, n) __arc_strnlen_user(s, n)
#else
extern unsigned long arc_clear_user_noinline(void __user *to,
unsigned long n);
@@ -734,8 +740,8 @@ extern long arc_strncpy_from_user_noinline (char *dst, const char __user *src,
extern long arc_strnlen_user_noinline(const char __user *src, long n);
#define __clear_user(d, n) arc_clear_user_noinline(d, n)
-#define __strncpy_from_user(d, s, n) arc_strncpy_from_user_noinline(d, s, n)
-#define __strnlen_user(s, n) arc_strnlen_user_noinline(s, n)
+#define strncpy_from_user(d, s, n) arc_strncpy_from_user_noinline(d, s, n)
+#define strnlen_user(s, n) arc_strnlen_user_noinline(s, n)
#endif
@@ -57,23 +57,27 @@ unsigned long raw_copy_to_user(void __user *to, const void *from,
__kernel_size_t __clear_user_hexagon(void __user *dest, unsigned long count);
#define __clear_user(a, s) __clear_user_hexagon((a), (s))
-#define __strncpy_from_user(dst, src, n) hexagon_strncpy_from_user(dst, src, n)
+extern long __strnlen_user(const char __user *src, long n);
-/* get around the ifndef in asm-generic/uaccess.h */
-#define __strnlen_user __strnlen_user
+static inline strnlen_user(const char __user *src, long n)
+{
+ if (!access_ok(src, 1))
+ return 0;
-extern long __strnlen_user(const char __user *src, long n);
+ return __strnlen_user(src, n);
+}
+/* get around the ifndef in asm-generic/uaccess.h */
+#define strnlen_user strnlen_user
-static inline long hexagon_strncpy_from_user(char *dst, const char __user *src,
- long n);
+static inline long strncpy_from_user(char *dst, const char __user *src, long n);
+#define strncpy_from_user strncpy_from_user
#include <asm-generic/uaccess.h>
/* Todo: an actual accelerated version of this. */
-static inline long hexagon_strncpy_from_user(char *dst, const char __user *src,
- long n)
+static inline long strncpy_from_user(char *dst, const char __user *src, long n)
{
- long res = __strnlen_user(src, n);
+ long res = strnlen_user(src, n);
if (unlikely(!res))
return -EFAULT;
@@ -23,16 +23,16 @@
extern unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n);
extern unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long n);
-extern long __strncpy_from_user(char *dst, const char __user *src, long count);
-extern long __strnlen_user(const void __user *str, long len);
+extern long strncpy_from_user(char *dst, const char __user *src, long count);
+extern long strnlen_user(const void __user *str, long len);
extern unsigned long __clear_user(void __user *mem, unsigned long len);
static inline int __access_ok(unsigned long addr, unsigned long size);
/* Teach asm-generic/uaccess.h that we have C functions for these. */
#define __access_ok __access_ok
#define __clear_user __clear_user
-#define __strnlen_user __strnlen_user
-#define __strncpy_from_user __strncpy_from_user
+#define strnlen_user strnlen_user
+#define strncpy_from_user strncpy_from_user
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_TO_USER
@@ -188,11 +188,14 @@ static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
return 0;
}
-long __strncpy_from_user(char *dst, const char __user *src, long count)
+long strncpy_from_user(char *dst, const char __user *src, long count)
{
long n;
char *ptr = dst;
+ if (!access_ok(src, 1))
+ return -EFAULT;
+
if (uaccess_kernel()) {
strncpy(dst, (__force void *) src, count);
return strnlen(dst, count);
@@ -246,11 +246,15 @@ extern int __get_user_bad(void) __attribute__((noreturn));
/*
* Copy a null terminated string from userspace.
*/
-#ifndef __strncpy_from_user
+#ifndef strncpy_from_user
static inline long
-__strncpy_from_user(char *dst, const char __user *src, long count)
+strncpy_from_user(char *dst, const char __user *src, long count)
{
char *tmp;
+
+ if (!access_ok(src, 1))
+ return -EFAULT;
+
strncpy(dst, (const char __force *)src, count);
for (tmp = dst; *tmp && count > 0; tmp++, count--)
;
@@ -258,24 +262,12 @@ __strncpy_from_user(char *dst, const char __user *src, long count)
}
#endif
-static inline long
-strncpy_from_user(char *dst, const char __user *src, long count)
-{
- if (!access_ok(src, 1))
- return -EFAULT;
- return __strncpy_from_user(dst, src, count);
-}
-
+#ifndef strnlen_user
/*
* Return the size of a string (including the ending 0)
*
* Return 0 on exception, a value greater than N if too long
- */
-#ifndef __strnlen_user
-#define __strnlen_user(s, n) (strnlen((s), (n)) + 1)
-#endif
-
-/*
+ *
* Unlike strnlen, strnlen_user includes the nul terminator in
* its returned count. Callers should check for a returned value
* greater than N as an indication the string is too long.
@@ -284,8 +276,10 @@ static inline long strnlen_user(const char __user *src, long n)
{
if (!access_ok(src, 1))
return 0;
- return __strnlen_user(src, n);
+
+ return strnlen(src, n) + 1;
}
+#endif
/*
* Zero Userspace