summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arc/include/asm/uaccess.h14
-rw-r--r--arch/csky/include/asm/uaccess.h8
-rw-r--r--arch/csky/lib/usercopy.c14
-rw-r--r--arch/hexagon/include/asm/uaccess.h22
-rw-r--r--arch/um/include/asm/uaccess.h8
-rw-r--r--arch/um/kernel/skas/uaccess.c14
-rw-r--r--include/asm-generic/uaccess.h28
7 files changed, 62 insertions, 46 deletions
diff --git a/arch/arc/include/asm/uaccess.h b/arch/arc/include/asm/uaccess.h
index ea40ec7f6cae..3476348f361e 100644
--- a/arch/arc/include/asm/uaccess.h
+++ b/arch/arc/include/asm/uaccess.h
@@ -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
diff --git a/arch/csky/include/asm/uaccess.h b/arch/csky/include/asm/uaccess.h
index ac83823fc437..e17c02a6709f 100644
--- a/arch/csky/include/asm/uaccess.h
+++ b/arch/csky/include/asm/uaccess.h
@@ -209,11 +209,11 @@ unsigned long raw_copy_to_user(void *to, const void *from, unsigned long n);
unsigned long __clear_user(void __user *to, unsigned long n);
#define __clear_user __clear_user
-long __strncpy_from_user(char *dst, const char *src, long count);
-#define __strncpy_from_user __strncpy_from_user
+long strncpy_from_user(char *dst, const char *src, long count);
+#define strncpy_from_user strncpy_from_user
-long __strnlen_user(const char *s, long n);
-#define __strnlen_user __strnlen_user
+long strnlen_user(const char *s, long n);
+#define strnlen_user strnlen_user
#include <asm/segment.h>
#include <asm-generic/uaccess.h>
diff --git a/arch/csky/lib/usercopy.c b/arch/csky/lib/usercopy.c
index c5d394a0ae78..05b36e9fd7d3 100644
--- a/arch/csky/lib/usercopy.c
+++ b/arch/csky/lib/usercopy.c
@@ -163,11 +163,14 @@ EXPORT_SYMBOL(raw_copy_to_user);
* If @count is smaller than the length of the string, copies @count bytes
* and returns @count.
*/
-long __strncpy_from_user(char *dst, const char *src, long count)
+long strncpy_from_user(char *dst, const char *src, long count)
{
long res, faultres;
int tmp;
+ if (!access_ok(s, 1))
+ return -EFAULT;
+
__asm__ __volatile__(
" cmpnei %3, 0 \n"
" bf 4f \n"
@@ -198,7 +201,7 @@ long __strncpy_from_user(char *dst, const char *src, long count)
return res;
}
-EXPORT_SYMBOL(__strncpy_from_user);
+EXPORT_SYMBOL(strncpy_from_user);
/*
* strnlen_user: - Get the size of a string in user space.
@@ -211,10 +214,13 @@ EXPORT_SYMBOL(__strncpy_from_user);
* On exception, returns 0.
* If the string is too long, returns a value greater than @n.
*/
-long __strnlen_user(const char *s, long n)
+long strnlen_user(const char *s, long n)
{
unsigned long res, tmp;
+ if (!access_ok(s, 1))
+ return -EFAULT;
+
__asm__ __volatile__(
" cmpnei %1, 0 \n"
" bf 3f \n"
@@ -242,7 +248,7 @@ long __strnlen_user(const char *s, long n)
return res;
}
-EXPORT_SYMBOL(__strnlen_user);
+EXPORT_SYMBOL(strnlen_user);
/*
* __clear_user: - Zero a block of memory in user space, with less checking.
diff --git a/arch/hexagon/include/asm/uaccess.h b/arch/hexagon/include/asm/uaccess.h
index c1019a736ff1..59aa3a50744f 100644
--- a/arch/hexagon/include/asm/uaccess.h
+++ b/arch/hexagon/include/asm/uaccess.h
@@ -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;
diff --git a/arch/um/include/asm/uaccess.h b/arch/um/include/asm/uaccess.h
index fe66d659acad..3bf209f683f8 100644
--- a/arch/um/include/asm/uaccess.h
+++ b/arch/um/include/asm/uaccess.h
@@ -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
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index 6c76df96e858..a509be911026 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -189,11 +189,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);
@@ -205,7 +208,7 @@ long __strncpy_from_user(char *dst, const char __user *src, long count)
return -EFAULT;
return strnlen(dst, count);
}
-EXPORT_SYMBOL(__strncpy_from_user);
+EXPORT_SYMBOL(strncpy_from_user);
static int clear_chunk(unsigned long addr, int len, void *unused)
{
@@ -236,10 +239,13 @@ static int strnlen_chunk(unsigned long str, int len, void *arg)
return 0;
}
-long __strnlen_user(const void __user *str, long len)
+long strnlen_user(const char __user *str, long len)
{
int count = 0, n;
+ if (!access_ok(str, 1))
+ return -EFAULT;
+
if (uaccess_kernel())
return strnlen((__force char*)str, len) + 1;
@@ -248,7 +254,7 @@ long __strnlen_user(const void __user *str, long len)
return count + 1;
return 0;
}
-EXPORT_SYMBOL(__strnlen_user);
+EXPORT_SYMBOL(strnlen_user);
/**
* arch_futex_atomic_op_inuser() - Atomic arithmetic operation with constant
diff --git a/include/asm-generic/uaccess.h b/include/asm-generic/uaccess.h
index a0b2f270dddc..2f8a5d3bbd57 100644
--- a/include/asm-generic/uaccess.h
+++ b/include/asm-generic/uaccess.h
@@ -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