diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-20 18:02:50 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-20 18:02:50 -0500 |
commit | dc6ec87d4c77029457a79fd6fa9b6f8304dc8348 (patch) | |
tree | 966392c36ef35c8cf388c0b7a57d1d7c1fe429dc | |
parent | 8a60ba0a0512c00553c9a20f83f7eabd2662ac0b (diff) | |
parent | 964f413323e8306ac0acb5e08ccdb5f12418835b (diff) |
Merge branch 'parisc-3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux
Pull parisc fixes from Helge Deller:
- revert an access_ok() patch which broke 32bit userspace on 64bit
kernels
- avoid a gcc miscompilation in two internal pa_memcpy() functions by
not inlining those
- do not export the definition of SOCK_NONBLOCK via uapi header (fixes
build of audit package)
- depending on the fault type we now correctly report either SIGBUS or
SIGSEGV
- a small fix to not compare a size_t variable for < 0
* 'parisc-3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
parisc: size_t is unsigned, so comparison size < 0 doesn't make sense.
parisc: improve SIGBUS/SIGSEGV error reporting
parisc: break out SOCK_NONBLOCK define to own asm header file
parisc: do not inline pa_memcpy() internal functions
Revert "parisc: implement full version of access_ok()"
-rw-r--r-- | arch/parisc/include/asm/socket.h | 11 | ||||
-rw-r--r-- | arch/parisc/include/asm/uaccess.h | 46 | ||||
-rw-r--r-- | arch/parisc/include/uapi/asm/socket.h | 11 | ||||
-rw-r--r-- | arch/parisc/lib/memcpy.c | 6 | ||||
-rw-r--r-- | arch/parisc/mm/fault.c | 22 |
5 files changed, 41 insertions, 55 deletions
diff --git a/arch/parisc/include/asm/socket.h b/arch/parisc/include/asm/socket.h new file mode 100644 index 000000000000..748016cb122d --- /dev/null +++ b/arch/parisc/include/asm/socket.h | |||
@@ -0,0 +1,11 @@ | |||
1 | #ifndef _ASM_SOCKET_H | ||
2 | #define _ASM_SOCKET_H | ||
3 | |||
4 | #include <uapi/asm/socket.h> | ||
5 | |||
6 | /* O_NONBLOCK clashes with the bits used for socket types. Therefore we | ||
7 | * have to define SOCK_NONBLOCK to a different value here. | ||
8 | */ | ||
9 | #define SOCK_NONBLOCK 0x40000000 | ||
10 | |||
11 | #endif /* _ASM_SOCKET_H */ | ||
diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h index 63f4dd0b49c2..4006964d8e12 100644 --- a/arch/parisc/include/asm/uaccess.h +++ b/arch/parisc/include/asm/uaccess.h | |||
@@ -4,14 +4,11 @@ | |||
4 | /* | 4 | /* |
5 | * User space memory access functions | 5 | * User space memory access functions |
6 | */ | 6 | */ |
7 | #include <asm/processor.h> | ||
8 | #include <asm/page.h> | 7 | #include <asm/page.h> |
9 | #include <asm/cache.h> | 8 | #include <asm/cache.h> |
10 | #include <asm/errno.h> | 9 | #include <asm/errno.h> |
11 | #include <asm-generic/uaccess-unaligned.h> | 10 | #include <asm-generic/uaccess-unaligned.h> |
12 | 11 | ||
13 | #include <linux/sched.h> | ||
14 | |||
15 | #define VERIFY_READ 0 | 12 | #define VERIFY_READ 0 |
16 | #define VERIFY_WRITE 1 | 13 | #define VERIFY_WRITE 1 |
17 | 14 | ||
@@ -36,43 +33,12 @@ extern int __get_user_bad(void); | |||
36 | extern int __put_kernel_bad(void); | 33 | extern int __put_kernel_bad(void); |
37 | extern int __put_user_bad(void); | 34 | extern int __put_user_bad(void); |
38 | 35 | ||
39 | 36 | static inline long access_ok(int type, const void __user * addr, | |
40 | /* | 37 | unsigned long size) |
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) | ||
46 | { | 38 | { |
47 | unsigned long __newaddr = addr + size; | 39 | return 1; |
48 | return (__newaddr < addr || __newaddr > limit || size > limit); | ||
49 | } | 40 | } |
50 | 41 | ||
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 | |||
76 | #define put_user __put_user | 42 | #define put_user __put_user |
77 | #define get_user __get_user | 43 | #define get_user __get_user |
78 | 44 | ||
@@ -253,11 +219,7 @@ extern long lstrnlen_user(const char __user *,long); | |||
253 | /* | 219 | /* |
254 | * Complex access routines -- macros | 220 | * Complex access routines -- macros |
255 | */ | 221 | */ |
256 | #ifdef CONFIG_COMPAT | 222 | #define user_addr_max() (~0UL) |
257 | #define user_addr_max() (TASK_SIZE) | ||
258 | #else | ||
259 | #define user_addr_max() (DEFAULT_TASK_SIZE) | ||
260 | #endif | ||
261 | 223 | ||
262 | #define strnlen_user lstrnlen_user | 224 | #define strnlen_user lstrnlen_user |
263 | #define strlen_user(str) lstrnlen_user(str, 0x7fffffffL) | 225 | #define strlen_user(str) lstrnlen_user(str, 0x7fffffffL) |
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h index 7c614d01f1fa..f33113a6141e 100644 --- a/arch/parisc/include/uapi/asm/socket.h +++ b/arch/parisc/include/uapi/asm/socket.h | |||
@@ -1,5 +1,5 @@ | |||
1 | #ifndef _ASM_SOCKET_H | 1 | #ifndef _UAPI_ASM_SOCKET_H |
2 | #define _ASM_SOCKET_H | 2 | #define _UAPI_ASM_SOCKET_H |
3 | 3 | ||
4 | #include <asm/sockios.h> | 4 | #include <asm/sockios.h> |
5 | 5 | ||
@@ -77,9 +77,4 @@ | |||
77 | 77 | ||
78 | #define SO_MAX_PACING_RATE 0x4048 | 78 | #define SO_MAX_PACING_RATE 0x4048 |
79 | 79 | ||
80 | /* O_NONBLOCK clashes with the bits used for socket types. Therefore we | 80 | #endif /* _UAPI_ASM_SOCKET_H */ |
81 | * have to define SOCK_NONBLOCK to a different value here. | ||
82 | */ | ||
83 | #define SOCK_NONBLOCK 0x40000000 | ||
84 | |||
85 | #endif /* _ASM_SOCKET_H */ | ||
diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c index b5507ec06b84..413dc1769299 100644 --- a/arch/parisc/lib/memcpy.c +++ b/arch/parisc/lib/memcpy.c | |||
@@ -161,7 +161,7 @@ static inline void prefetch_dst(const void *addr) | |||
161 | /* Copy from a not-aligned src to an aligned dst, using shifts. Handles 4 words | 161 | /* Copy from a not-aligned src to an aligned dst, using shifts. Handles 4 words |
162 | * per loop. This code is derived from glibc. | 162 | * per loop. This code is derived from glibc. |
163 | */ | 163 | */ |
164 | static inline unsigned long copy_dstaligned(unsigned long dst, | 164 | static noinline unsigned long copy_dstaligned(unsigned long dst, |
165 | unsigned long src, unsigned long len) | 165 | unsigned long src, unsigned long len) |
166 | { | 166 | { |
167 | /* gcc complains that a2 and a3 may be uninitialized, but actually | 167 | /* gcc complains that a2 and a3 may be uninitialized, but actually |
@@ -276,7 +276,7 @@ handle_store_error: | |||
276 | /* Returns PA_MEMCPY_OK, PA_MEMCPY_LOAD_ERROR or PA_MEMCPY_STORE_ERROR. | 276 | /* Returns PA_MEMCPY_OK, PA_MEMCPY_LOAD_ERROR or PA_MEMCPY_STORE_ERROR. |
277 | * In case of an access fault the faulty address can be read from the per_cpu | 277 | * In case of an access fault the faulty address can be read from the per_cpu |
278 | * exception data struct. */ | 278 | * exception data struct. */ |
279 | static unsigned long pa_memcpy_internal(void *dstp, const void *srcp, | 279 | static noinline unsigned long pa_memcpy_internal(void *dstp, const void *srcp, |
280 | unsigned long len) | 280 | unsigned long len) |
281 | { | 281 | { |
282 | register unsigned long src, dst, t1, t2, t3; | 282 | register unsigned long src, dst, t1, t2, t3; |
@@ -529,7 +529,7 @@ long probe_kernel_read(void *dst, const void *src, size_t size) | |||
529 | { | 529 | { |
530 | unsigned long addr = (unsigned long)src; | 530 | unsigned long addr = (unsigned long)src; |
531 | 531 | ||
532 | if (size < 0 || addr < PAGE_SIZE) | 532 | if (addr < PAGE_SIZE) |
533 | return -EFAULT; | 533 | return -EFAULT; |
534 | 534 | ||
535 | /* check for I/O space F_EXTEND(0xfff00000) access as well? */ | 535 | /* check for I/O space F_EXTEND(0xfff00000) access as well? */ |
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index 7584a5df0fa4..9d08c71a967e 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c | |||
@@ -282,16 +282,34 @@ bad_area: | |||
282 | #endif | 282 | #endif |
283 | switch (code) { | 283 | switch (code) { |
284 | case 15: /* Data TLB miss fault/Data page fault */ | 284 | case 15: /* Data TLB miss fault/Data page fault */ |
285 | /* send SIGSEGV when outside of vma */ | ||
286 | if (!vma || | ||
287 | address < vma->vm_start || address > vma->vm_end) { | ||
288 | si.si_signo = SIGSEGV; | ||
289 | si.si_code = SEGV_MAPERR; | ||
290 | break; | ||
291 | } | ||
292 | |||
293 | /* send SIGSEGV for wrong permissions */ | ||
294 | if ((vma->vm_flags & acc_type) != acc_type) { | ||
295 | si.si_signo = SIGSEGV; | ||
296 | si.si_code = SEGV_ACCERR; | ||
297 | break; | ||
298 | } | ||
299 | |||
300 | /* probably address is outside of mapped file */ | ||
301 | /* fall through */ | ||
285 | case 17: /* NA data TLB miss / page fault */ | 302 | case 17: /* NA data TLB miss / page fault */ |
286 | case 18: /* Unaligned access - PCXS only */ | 303 | case 18: /* Unaligned access - PCXS only */ |
287 | si.si_signo = SIGBUS; | 304 | si.si_signo = SIGBUS; |
288 | si.si_code = BUS_ADRERR; | 305 | si.si_code = (code == 18) ? BUS_ADRALN : BUS_ADRERR; |
289 | break; | 306 | break; |
290 | case 16: /* Non-access instruction TLB miss fault */ | 307 | case 16: /* Non-access instruction TLB miss fault */ |
291 | case 26: /* PCXL: Data memory access rights trap */ | 308 | case 26: /* PCXL: Data memory access rights trap */ |
292 | default: | 309 | default: |
293 | si.si_signo = SIGSEGV; | 310 | si.si_signo = SIGSEGV; |
294 | si.si_code = SEGV_MAPERR; | 311 | si.si_code = (code == 26) ? SEGV_ACCERR : SEGV_MAPERR; |
312 | break; | ||
295 | } | 313 | } |
296 | si.si_errno = 0; | 314 | si.si_errno = 0; |
297 | si.si_addr = (void __user *) address; | 315 | si.si_addr = (void __user *) address; |