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()"
This commit is contained in:
11
arch/parisc/include/asm/socket.h
Normal file
11
arch/parisc/include/asm/socket.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#ifndef _ASM_SOCKET_H
|
||||||
|
#define _ASM_SOCKET_H
|
||||||
|
|
||||||
|
#include <uapi/asm/socket.h>
|
||||||
|
|
||||||
|
/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
|
||||||
|
* have to define SOCK_NONBLOCK to a different value here.
|
||||||
|
*/
|
||||||
|
#define SOCK_NONBLOCK 0x40000000
|
||||||
|
|
||||||
|
#endif /* _ASM_SOCKET_H */
|
@@ -4,14 +4,11 @@
|
|||||||
/*
|
/*
|
||||||
* User space memory access functions
|
* User space memory access functions
|
||||||
*/
|
*/
|
||||||
#include <asm/processor.h>
|
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm/cache.h>
|
#include <asm/cache.h>
|
||||||
#include <asm/errno.h>
|
#include <asm/errno.h>
|
||||||
#include <asm-generic/uaccess-unaligned.h>
|
#include <asm-generic/uaccess-unaligned.h>
|
||||||
|
|
||||||
#include <linux/sched.h>
|
|
||||||
|
|
||||||
#define VERIFY_READ 0
|
#define VERIFY_READ 0
|
||||||
#define VERIFY_WRITE 1
|
#define VERIFY_WRITE 1
|
||||||
|
|
||||||
@@ -36,43 +33,12 @@ extern int __get_user_bad(void);
|
|||||||
extern int __put_kernel_bad(void);
|
extern int __put_kernel_bad(void);
|
||||||
extern int __put_user_bad(void);
|
extern int __put_user_bad(void);
|
||||||
|
|
||||||
|
static inline long access_ok(int type, const void __user * addr,
|
||||||
/*
|
unsigned long size)
|
||||||
* Test whether a block of memory is a valid user space address.
|
|
||||||
* Returns 0 if the range is valid, nonzero otherwise.
|
|
||||||
*/
|
|
||||||
static inline int __range_not_ok(unsigned long addr, unsigned long size,
|
|
||||||
unsigned long limit)
|
|
||||||
{
|
{
|
||||||
unsigned long __newaddr = addr + size;
|
return 1;
|
||||||
return (__newaddr < addr || __newaddr > limit || size > limit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* access_ok: - Checks if a user space pointer is valid
|
|
||||||
* @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that
|
|
||||||
* %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe
|
|
||||||
* to write to a block, it is always safe to read from it.
|
|
||||||
* @addr: User space pointer to start of block to check
|
|
||||||
* @size: Size of block to check
|
|
||||||
*
|
|
||||||
* Context: User context only. This function may sleep.
|
|
||||||
*
|
|
||||||
* Checks if a pointer to a block of memory in user space is valid.
|
|
||||||
*
|
|
||||||
* Returns true (nonzero) if the memory block may be valid, false (zero)
|
|
||||||
* if it is definitely invalid.
|
|
||||||
*
|
|
||||||
* Note that, depending on architecture, this function probably just
|
|
||||||
* checks that the pointer is in the user space range - after calling
|
|
||||||
* this function, memory access functions may still return -EFAULT.
|
|
||||||
*/
|
|
||||||
#define access_ok(type, addr, size) \
|
|
||||||
( __chk_user_ptr(addr), \
|
|
||||||
!__range_not_ok((unsigned long) (__force void *) (addr), \
|
|
||||||
size, user_addr_max()) \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define put_user __put_user
|
#define put_user __put_user
|
||||||
#define get_user __get_user
|
#define get_user __get_user
|
||||||
|
|
||||||
@@ -253,11 +219,7 @@ extern long lstrnlen_user(const char __user *,long);
|
|||||||
/*
|
/*
|
||||||
* Complex access routines -- macros
|
* Complex access routines -- macros
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_COMPAT
|
#define user_addr_max() (~0UL)
|
||||||
#define user_addr_max() (TASK_SIZE)
|
|
||||||
#else
|
|
||||||
#define user_addr_max() (DEFAULT_TASK_SIZE)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define strnlen_user lstrnlen_user
|
#define strnlen_user lstrnlen_user
|
||||||
#define strlen_user(str) lstrnlen_user(str, 0x7fffffffL)
|
#define strlen_user(str) lstrnlen_user(str, 0x7fffffffL)
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#ifndef _ASM_SOCKET_H
|
#ifndef _UAPI_ASM_SOCKET_H
|
||||||
#define _ASM_SOCKET_H
|
#define _UAPI_ASM_SOCKET_H
|
||||||
|
|
||||||
#include <asm/sockios.h>
|
#include <asm/sockios.h>
|
||||||
|
|
||||||
@@ -77,9 +77,4 @@
|
|||||||
|
|
||||||
#define SO_MAX_PACING_RATE 0x4048
|
#define SO_MAX_PACING_RATE 0x4048
|
||||||
|
|
||||||
/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
|
#endif /* _UAPI_ASM_SOCKET_H */
|
||||||
* have to define SOCK_NONBLOCK to a different value here.
|
|
||||||
*/
|
|
||||||
#define SOCK_NONBLOCK 0x40000000
|
|
||||||
|
|
||||||
#endif /* _ASM_SOCKET_H */
|
|
||||||
|
@@ -161,7 +161,7 @@ static inline void prefetch_dst(const void *addr)
|
|||||||
/* Copy from a not-aligned src to an aligned dst, using shifts. Handles 4 words
|
/* Copy from a not-aligned src to an aligned dst, using shifts. Handles 4 words
|
||||||
* per loop. This code is derived from glibc.
|
* per loop. This code is derived from glibc.
|
||||||
*/
|
*/
|
||||||
static inline unsigned long copy_dstaligned(unsigned long dst,
|
static noinline unsigned long copy_dstaligned(unsigned long dst,
|
||||||
unsigned long src, unsigned long len)
|
unsigned long src, unsigned long len)
|
||||||
{
|
{
|
||||||
/* gcc complains that a2 and a3 may be uninitialized, but actually
|
/* gcc complains that a2 and a3 may be uninitialized, but actually
|
||||||
@@ -276,7 +276,7 @@ handle_store_error:
|
|||||||
/* Returns PA_MEMCPY_OK, PA_MEMCPY_LOAD_ERROR or PA_MEMCPY_STORE_ERROR.
|
/* Returns PA_MEMCPY_OK, PA_MEMCPY_LOAD_ERROR or PA_MEMCPY_STORE_ERROR.
|
||||||
* In case of an access fault the faulty address can be read from the per_cpu
|
* In case of an access fault the faulty address can be read from the per_cpu
|
||||||
* exception data struct. */
|
* exception data struct. */
|
||||||
static unsigned long pa_memcpy_internal(void *dstp, const void *srcp,
|
static noinline unsigned long pa_memcpy_internal(void *dstp, const void *srcp,
|
||||||
unsigned long len)
|
unsigned long len)
|
||||||
{
|
{
|
||||||
register unsigned long src, dst, t1, t2, t3;
|
register unsigned long src, dst, t1, t2, t3;
|
||||||
@@ -529,7 +529,7 @@ long probe_kernel_read(void *dst, const void *src, size_t size)
|
|||||||
{
|
{
|
||||||
unsigned long addr = (unsigned long)src;
|
unsigned long addr = (unsigned long)src;
|
||||||
|
|
||||||
if (size < 0 || addr < PAGE_SIZE)
|
if (addr < PAGE_SIZE)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
/* check for I/O space F_EXTEND(0xfff00000) access as well? */
|
/* check for I/O space F_EXTEND(0xfff00000) access as well? */
|
||||||
|
@@ -282,16 +282,34 @@ bad_area:
|
|||||||
#endif
|
#endif
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 15: /* Data TLB miss fault/Data page fault */
|
case 15: /* Data TLB miss fault/Data page fault */
|
||||||
|
/* send SIGSEGV when outside of vma */
|
||||||
|
if (!vma ||
|
||||||
|
address < vma->vm_start || address > vma->vm_end) {
|
||||||
|
si.si_signo = SIGSEGV;
|
||||||
|
si.si_code = SEGV_MAPERR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send SIGSEGV for wrong permissions */
|
||||||
|
if ((vma->vm_flags & acc_type) != acc_type) {
|
||||||
|
si.si_signo = SIGSEGV;
|
||||||
|
si.si_code = SEGV_ACCERR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* probably address is outside of mapped file */
|
||||||
|
/* fall through */
|
||||||
case 17: /* NA data TLB miss / page fault */
|
case 17: /* NA data TLB miss / page fault */
|
||||||
case 18: /* Unaligned access - PCXS only */
|
case 18: /* Unaligned access - PCXS only */
|
||||||
si.si_signo = SIGBUS;
|
si.si_signo = SIGBUS;
|
||||||
si.si_code = BUS_ADRERR;
|
si.si_code = (code == 18) ? BUS_ADRALN : BUS_ADRERR;
|
||||||
break;
|
break;
|
||||||
case 16: /* Non-access instruction TLB miss fault */
|
case 16: /* Non-access instruction TLB miss fault */
|
||||||
case 26: /* PCXL: Data memory access rights trap */
|
case 26: /* PCXL: Data memory access rights trap */
|
||||||
default:
|
default:
|
||||||
si.si_signo = SIGSEGV;
|
si.si_signo = SIGSEGV;
|
||||||
si.si_code = SEGV_MAPERR;
|
si.si_code = (code == 26) ? SEGV_ACCERR : SEGV_MAPERR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
si.si_errno = 0;
|
si.si_errno = 0;
|
||||||
si.si_addr = (void __user *) address;
|
si.si_addr = (void __user *) address;
|
||||||
|
Reference in New Issue
Block a user