summaryrefslogtreecommitdiffstats
path: root/include/asm-sh/uaccess.h
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2006-09-27 17:07:07 +0900
committerPaul Mundt <lethal@linux-sh.org>2006-09-27 17:07:07 +0900
commit2991be725260d6fec11691a6138b9d71de949956 (patch)
tree407241b126eed902bacba4e02043930c6ce087b4 /include/asm-sh/uaccess.h
parent0f08f338083cc1d68788ccbccc44bd0502fc57ae (diff)
downloadkernel-crypto-2991be725260d6fec11691a6138b9d71de949956.tar.gz
kernel-crypto-2991be725260d6fec11691a6138b9d71de949956.tar.xz
kernel-crypto-2991be725260d6fec11691a6138b9d71de949956.zip
sh: Fixup __strnlen_user() behaviour.
Drop TIF_USERSPACE and add addr_limit to the thread_info struct. Subsequently, use that for address checking in strnlen_user() to ward off bogus -EFAULTs. Make __strnlen_user() return 0 on exception, rather than -EFAULT. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'include/asm-sh/uaccess.h')
-rw-r--r--include/asm-sh/uaccess.h65
1 files changed, 13 insertions, 52 deletions
diff --git a/include/asm-sh/uaccess.h b/include/asm-sh/uaccess.h
index 2cb01861e7c..6c0014dd2ef 100644
--- a/include/asm-sh/uaccess.h
+++ b/include/asm-sh/uaccess.h
@@ -16,21 +16,9 @@
#include <linux/errno.h>
#include <linux/sched.h>
-/*
- * NOTE: Macro/functions in this file depends on threads_info.h implementation.
- * Assumes:
- * TI_FLAGS == 8
- * TIF_USERSPACE == 31
- * USER_ADDR_LIMIT == 0x80000000
- */
-
#define VERIFY_READ 0
#define VERIFY_WRITE 1
-typedef struct {
- unsigned int is_user_space;
-} mm_segment_t;
-
/*
* The fs value determines whether argument validity checking should be
* performed or not. If get_fs() == USER_DS, checking is performed, with
@@ -40,12 +28,14 @@ typedef struct {
*/
#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
-#define segment_eq(a,b) ((a).is_user_space == (b).is_user_space)
-#define USER_ADDR_LIMIT 0x80000000
+#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFFUL)
+#define USER_DS MAKE_MM_SEG(PAGE_OFFSET)
+
+#define segment_eq(a,b) ((a).seg == (b).seg)
-#define KERNEL_DS MAKE_MM_SEG(0)
-#define USER_DS MAKE_MM_SEG(1)
+#define __addr_ok(addr) \
+ ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg))
#define get_ds() (KERNEL_DS)
@@ -76,31 +66,8 @@ static inline int __access_ok(unsigned long addr, unsigned long size)
return ((addr >= memory_start) && ((addr + size) < memory_end));
}
#else /* CONFIG_MMU */
-static inline mm_segment_t get_fs(void)
-{
- return MAKE_MM_SEG(test_thread_flag(TIF_USERSPACE));
-}
-
-static inline void set_fs(mm_segment_t s)
-{
- unsigned long ti, flag;
- __asm__ __volatile__(
- "stc r7_bank, %0\n\t"
- "mov.l @(8,%0), %1\n\t"
- "shal %1\n\t"
- "cmp/pl %2\n\t"
- "rotcr %1\n\t"
- "mov.l %1, @(8,%0)"
- : "=&r" (ti), "=&r" (flag)
- : "r" (s.is_user_space)
- : "t");
-/****
- if (s.is_user_space)
- set_thread_flag(TIF_USERSPACE);
- else
- clear_thread_flag(TIF_USERSPACE);
-****/
-}
+#define get_fs() (current_thread_info()->addr_limit)
+#define set_fs(x) (current_thread_info()->addr_limit = (x))
/*
* __access_ok: Check if address with size is OK or not.
@@ -108,7 +75,7 @@ static inline void set_fs(mm_segment_t s)
* We do three checks:
* (1) is it user space?
* (2) addr + size --> carry?
- * (3) addr + size >= 0x80000000 (USER_ADDR_LIMIT)
+ * (3) addr + size >= 0x80000000 (PAGE_OFFSET)
*
* (1) (2) (3) | RESULT
* 0 0 0 | ok
@@ -541,7 +508,7 @@ static __inline__ long __strnlen_user(const char __user *__s, long __n)
"3:\n\t"
"mov.l 4f, %1\n\t"
"jmp @%1\n\t"
- " mov %5, %0\n"
+ " mov #0, %0\n"
".balign 4\n"
"4: .long 2b\n"
".previous\n"
@@ -550,26 +517,20 @@ static __inline__ long __strnlen_user(const char __user *__s, long __n)
" .long 1b,3b\n"
".previous"
: "=z" (res), "=&r" (__dummy)
- : "0" (0), "r" (__s), "r" (__n), "i" (-EFAULT)
+ : "0" (0), "r" (__s), "r" (__n)
: "t");
return res;
}
static __inline__ long strnlen_user(const char __user *s, long n)
{
- if (!access_ok(VERIFY_READ, s, n))
+ if (!__addr_ok(s))
return 0;
else
return __strnlen_user(s, n);
}
-static __inline__ long strlen_user(const char __user *s)
-{
- if (!access_ok(VERIFY_READ, s, 0))
- return 0;
- else
- return __strnlen_user(s, ~0UL >> 1);
-}
+#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
/*
* The exception table consists of pairs of addresses: the first is the