diff options
author | Helge Deller <deller@gmx.de> | 2013-06-29 08:03:14 -0400 |
---|---|---|
committer | Helge Deller <deller@gmx.de> | 2013-11-07 16:29:14 -0500 |
commit | 63379c135331c724d40a87b98eb62d2122981341 (patch) | |
tree | 35ef859d3afae3d73c0cb92c1dbd7cb79227deb3 | |
parent | 3a7452b4449d34f2eec377e45036f5e0808aff09 (diff) |
parisc: implement full version of access_ok()
Up to now PA-RISC could live with a trivial version of access_ok().
Our fault handlers can correctly handle fault cases.
But testcases showed that we need a better access check else we won't
always return correct errno failure codes to userspace.
Problem showed up during 32bit userspace tests in which writev() used a
32bit memory area and length which would then wrap around on 64bit
kernel.
Signed-off-by: Helge Deller <deller@gmx.de>
-rw-r--r-- | arch/parisc/include/asm/uaccess.h | 46 |
1 files changed, 42 insertions, 4 deletions
diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h index 4006964d8e12..63f4dd0b49c2 100644 --- a/arch/parisc/include/asm/uaccess.h +++ b/arch/parisc/include/asm/uaccess.h | |||
@@ -4,11 +4,14 @@ | |||
4 | /* | 4 | /* |
5 | * User space memory access functions | 5 | * User space memory access functions |
6 | */ | 6 | */ |
7 | #include <asm/processor.h> | ||
7 | #include <asm/page.h> | 8 | #include <asm/page.h> |
8 | #include <asm/cache.h> | 9 | #include <asm/cache.h> |
9 | #include <asm/errno.h> | 10 | #include <asm/errno.h> |
10 | #include <asm-generic/uaccess-unaligned.h> | 11 | #include <asm-generic/uaccess-unaligned.h> |
11 | 12 | ||
13 | #include <linux/sched.h> | ||
14 | |||
12 | #define VERIFY_READ 0 | 15 | #define VERIFY_READ 0 |
13 | #define VERIFY_WRITE 1 | 16 | #define VERIFY_WRITE 1 |
14 | 17 | ||
@@ -33,12 +36,43 @@ extern int __get_user_bad(void); | |||
33 | extern int __put_kernel_bad(void); | 36 | extern int __put_kernel_bad(void); |
34 | extern int __put_user_bad(void); | 37 | extern int __put_user_bad(void); |
35 | 38 | ||
36 | static inline long access_ok(int type, const void __user * addr, | 39 | |
37 | unsigned long size) | 40 | /* |
41 | * Test whether a block of memory is a valid user space address. | ||
42 | * Returns 0 if the range is valid, nonzero otherwise. | ||
43 | */ | ||
44 | static inline int __range_not_ok(unsigned long addr, unsigned long size, | ||
45 | unsigned long limit) | ||
38 | { | 46 | { |
39 | return 1; | 47 | unsigned long __newaddr = addr + size; |
48 | return (__newaddr < addr || __newaddr > limit || size > limit); | ||
40 | } | 49 | } |
41 | 50 | ||
51 | /** | ||
52 | * access_ok: - Checks if a user space pointer is valid | ||
53 | * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that | ||
54 | * %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe | ||
55 | * to write to a block, it is always safe to read from it. | ||
56 | * @addr: User space pointer to start of block to check | ||
57 | * @size: Size of block to check | ||
58 | * | ||
59 | * Context: User context only. This function may sleep. | ||
60 | * | ||
61 | * Checks if a pointer to a block of memory in user space is valid. | ||
62 | * | ||
63 | * Returns true (nonzero) if the memory block may be valid, false (zero) | ||
64 | * if it is definitely invalid. | ||
65 | * | ||
66 | * Note that, depending on architecture, this function probably just | ||
67 | * checks that the pointer is in the user space range - after calling | ||
68 | * this function, memory access functions may still return -EFAULT. | ||
69 | */ | ||
70 | #define access_ok(type, addr, size) \ | ||
71 | ( __chk_user_ptr(addr), \ | ||
72 | !__range_not_ok((unsigned long) (__force void *) (addr), \ | ||
73 | size, user_addr_max()) \ | ||
74 | ) | ||
75 | |||
42 | #define put_user __put_user | 76 | #define put_user __put_user |
43 | #define get_user __get_user | 77 | #define get_user __get_user |
44 | 78 | ||
@@ -219,7 +253,11 @@ extern long lstrnlen_user(const char __user *,long); | |||
219 | /* | 253 | /* |
220 | * Complex access routines -- macros | 254 | * Complex access routines -- macros |
221 | */ | 255 | */ |
222 | #define user_addr_max() (~0UL) | 256 | #ifdef CONFIG_COMPAT |
257 | #define user_addr_max() (TASK_SIZE) | ||
258 | #else | ||
259 | #define user_addr_max() (DEFAULT_TASK_SIZE) | ||
260 | #endif | ||
223 | 261 | ||
224 | #define strnlen_user lstrnlen_user | 262 | #define strnlen_user lstrnlen_user |
225 | #define strlen_user(str) lstrnlen_user(str, 0x7fffffffL) | 263 | #define strlen_user(str) lstrnlen_user(str, 0x7fffffffL) |