diff options
Diffstat (limited to 'arch/um')
-rw-r--r-- | arch/um/Kconfig | 2 | ||||
-rw-r--r-- | arch/um/include/asm/uaccess.h | 5 | ||||
-rw-r--r-- | arch/um/kernel/skas/uaccess.c | 14 |
3 files changed, 13 insertions, 8 deletions
diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 0561b73cfd9a..77e66d3719f6 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -7,6 +7,8 @@ config UML default y select ARCH_EPHEMERAL_INODES select ARCH_HAS_KCOV + select ARCH_HAS_STRNCPY_FROM_USER + select ARCH_HAS_STRNLEN_USER select ARCH_NO_PREEMPT select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_SECCOMP_FILTER diff --git a/arch/um/include/asm/uaccess.h b/arch/um/include/asm/uaccess.h index fe66d659acad..191ef36dd543 100644 --- a/arch/um/include/asm/uaccess.h +++ b/arch/um/include/asm/uaccess.h @@ -23,16 +23,13 @@ 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 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 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 |