aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2013-06-29 08:03:14 -0400
committerHelge Deller <deller@gmx.de>2013-11-07 16:29:14 -0500
commit63379c135331c724d40a87b98eb62d2122981341 (patch)
tree35ef859d3afae3d73c0cb92c1dbd7cb79227deb3
parent3a7452b4449d34f2eec377e45036f5e0808aff09 (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.h46
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);
33extern int __put_kernel_bad(void); 36extern int __put_kernel_bad(void);
34extern int __put_user_bad(void); 37extern int __put_user_bad(void);
35 38
36static 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 */
44static 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)