Commit 89cbec71 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'work.uaccess-unaligned' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull uacess-unaligned removal from Al Viro:
 "That stuff had just one user, and an exotic one, at that - binfmt_flat
  on arm and m68k"

* 'work.uaccess-unaligned' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  kill {__,}{get,put}_user_unaligned()
  binfmt_flat: flat_{get,put}_addr_from_rp() should be able to fail
parents 2173bd06 3170d8d2
...@@ -5,12 +5,31 @@ ...@@ -5,12 +5,31 @@
#ifndef __ARM_FLAT_H__ #ifndef __ARM_FLAT_H__
#define __ARM_FLAT_H__ #define __ARM_FLAT_H__
#include <linux/uaccess.h>
#define flat_argvp_envp_on_stack() 1 #define flat_argvp_envp_on_stack() 1
#define flat_old_ram_flag(flags) (flags) #define flat_old_ram_flag(flags) (flags)
#define flat_reloc_valid(reloc, size) ((reloc) <= (size)) #define flat_reloc_valid(reloc, size) ((reloc) <= (size))
#define flat_get_addr_from_rp(rp, relval, flags, persistent) \
({ unsigned long __val; __get_user_unaligned(__val, rp); __val; }) static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
#define flat_put_addr_at_rp(rp, val, relval) __put_user_unaligned(val, rp) u32 *addr, u32 *persistent)
{
#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
return copy_from_user(addr, rp, 4) ? -EFAULT : 0;
#else
return get_user(*addr, rp);
#endif
}
static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
{
#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
return copy_to_user(rp, &addr, 4) ? -EFAULT : 0;
#else
return put_user(addr, rp);
#endif
}
#define flat_get_relocate_addr(rel) (rel) #define flat_get_relocate_addr(rel) (rel)
#define flat_set_persistent(relval, p) 0 #define flat_set_persistent(relval, p) 0
......
...@@ -17,13 +17,6 @@ ...@@ -17,13 +17,6 @@
#include <asm/unified.h> #include <asm/unified.h>
#include <asm/compiler.h> #include <asm/compiler.h>
#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
#include <asm-generic/uaccess-unaligned.h>
#else
#define __get_user_unaligned __get_user
#define __put_user_unaligned __put_user
#endif
#include <asm/extable.h> #include <asm/extable.h>
/* /*
......
...@@ -254,8 +254,6 @@ do { \ ...@@ -254,8 +254,6 @@ do { \
(void)0; \ (void)0; \
}) })
#define __get_user_unaligned __get_user
#define get_user(x, ptr) \ #define get_user(x, ptr) \
({ \ ({ \
__typeof__(*(ptr)) __user *__p = (ptr); \ __typeof__(*(ptr)) __user *__p = (ptr); \
...@@ -320,8 +318,6 @@ do { \ ...@@ -320,8 +318,6 @@ do { \
(void)0; \ (void)0; \
}) })
#define __put_user_unaligned __put_user
#define put_user(x, ptr) \ #define put_user(x, ptr) \
({ \ ({ \
__typeof__(*(ptr)) __user *__p = (ptr); \ __typeof__(*(ptr)) __user *__p = (ptr); \
......
...@@ -14,23 +14,28 @@ ...@@ -14,23 +14,28 @@
#define flat_argvp_envp_on_stack() 0 #define flat_argvp_envp_on_stack() 0
#define flat_old_ram_flag(flags) (flags) #define flat_old_ram_flag(flags) (flags)
extern unsigned long bfin_get_addr_from_rp (unsigned long *ptr, extern unsigned long bfin_get_addr_from_rp (u32 *ptr, u32 relval,
unsigned long relval, u32 flags, u32 *persistent);
unsigned long flags,
unsigned long *persistent);
extern void bfin_put_addr_at_rp(unsigned long *ptr, unsigned long addr, extern void bfin_put_addr_at_rp(u32 *ptr, u32 addr, u32 relval);
unsigned long relval);
/* The amount by which a relocation can exceed the program image limits /* The amount by which a relocation can exceed the program image limits
without being regarded as an error. */ without being regarded as an error. */
#define flat_reloc_valid(reloc, size) ((reloc) <= (size)) #define flat_reloc_valid(reloc, size) ((reloc) <= (size))
#define flat_get_addr_from_rp(rp, relval, flags, persistent) \ static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
bfin_get_addr_from_rp(rp, relval, flags, persistent) u32 *addr, u32 *persistent)
#define flat_put_addr_at_rp(rp, val, relval) \ {
bfin_put_addr_at_rp(rp, val, relval) *addr = bfin_get_addr_from_rp(rp, relval, flags, persistent);
return 0;
}
static inline int flat_put_addr_at_rp(u32 __user *rp, u32 val, u32 relval)
{
bfin_put_addr_at_rp(rp, val, relval);
return 0;
}
/* Convert a relocation entry into an address. */ /* Convert a relocation entry into an address. */
static inline unsigned long static inline unsigned long
......
...@@ -13,14 +13,14 @@ ...@@ -13,14 +13,14 @@
#define FLAT_BFIN_RELOC_TYPE_16H_BIT 1 #define FLAT_BFIN_RELOC_TYPE_16H_BIT 1
#define FLAT_BFIN_RELOC_TYPE_32_BIT 2 #define FLAT_BFIN_RELOC_TYPE_32_BIT 2
unsigned long bfin_get_addr_from_rp(unsigned long *ptr, unsigned long bfin_get_addr_from_rp(u32 *ptr,
unsigned long relval, u32 relval,
unsigned long flags, u32 flags,
unsigned long *persistent) u32 *persistent)
{ {
unsigned short *usptr = (unsigned short *)ptr; unsigned short *usptr = (unsigned short *)ptr;
int type = (relval >> 26) & 7; int type = (relval >> 26) & 7;
unsigned long val; u32 val;
switch (type) { switch (type) {
case FLAT_BFIN_RELOC_TYPE_16_BIT: case FLAT_BFIN_RELOC_TYPE_16_BIT:
...@@ -59,8 +59,7 @@ EXPORT_SYMBOL(bfin_get_addr_from_rp); ...@@ -59,8 +59,7 @@ EXPORT_SYMBOL(bfin_get_addr_from_rp);
* Insert the address ADDR into the symbol reference at RP; * Insert the address ADDR into the symbol reference at RP;
* RELVAL is the raw relocation-table entry from which RP is derived * RELVAL is the raw relocation-table entry from which RP is derived
*/ */
void bfin_put_addr_at_rp(unsigned long *ptr, unsigned long addr, void bfin_put_addr_at_rp(u32 *ptr, u32 addr, u32 relval)
unsigned long relval)
{ {
unsigned short *usptr = (unsigned short *)ptr; unsigned short *usptr = (unsigned short *)ptr;
int type = (relval >> 26) & 7; int type = (relval >> 26) & 7;
......
#ifndef __ASM_C6X_FLAT_H #ifndef __ASM_C6X_FLAT_H
#define __ASM_C6X_FLAT_H #define __ASM_C6X_FLAT_H
#include <asm/unaligned.h>
#define flat_argvp_envp_on_stack() 0 #define flat_argvp_envp_on_stack() 0
#define flat_old_ram_flag(flags) (flags) #define flat_old_ram_flag(flags) (flags)
#define flat_reloc_valid(reloc, size) ((reloc) <= (size)) #define flat_reloc_valid(reloc, size) ((reloc) <= (size))
#define flat_get_addr_from_rp(rp, relval, flags, p) get_unaligned(rp) static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
#define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val, rp) u32 *addr, u32 *persistent)
{
*addr = get_unaligned((__force u32 *)rp);
return 0;
}
static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
{
put_unaligned(addr, (__force u32 *)rp);
return 0;
}
#define flat_get_relocate_addr(rel) (rel) #define flat_get_relocate_addr(rel) (rel)
#define flat_set_persistent(relval, p) 0 #define flat_set_persistent(relval, p) 0
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef __H8300_FLAT_H__ #ifndef __H8300_FLAT_H__
#define __H8300_FLAT_H__ #define __H8300_FLAT_H__
#include <asm/unaligned.h>
#define flat_argvp_envp_on_stack() 1 #define flat_argvp_envp_on_stack() 1
#define flat_old_ram_flag(flags) 1 #define flat_old_ram_flag(flags) 1
#define flat_reloc_valid(reloc, size) ((reloc) <= (size)) #define flat_reloc_valid(reloc, size) ((reloc) <= (size))
...@@ -18,11 +20,21 @@ ...@@ -18,11 +20,21 @@
*/ */
#define flat_get_relocate_addr(rel) (rel & ~0x00000001) #define flat_get_relocate_addr(rel) (rel & ~0x00000001)
#define flat_get_addr_from_rp(rp, relval, flags, persistent) \ static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
({(void)persistent; \ u32 *addr, u32 *persistent)
get_unaligned(rp) & (((flags) & FLAT_FLAG_GOTPIC) ? \ {
0xffffffff : 0x00ffffff); }) u32 val = get_unaligned((__force u32 *)rp);
#define flat_put_addr_at_rp(rp, addr, rel) \ if (!(flags & FLAT_FLAG_GOTPIC)
put_unaligned(((*(char *)(rp)) << 24) | ((addr) & 0x00ffffff), (rp)) val &= 0x00ffffff;
*addr = val;
return 0;
}
static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
{
u32 *p = (__force u32 *)rp;
put_unaligned((addr & 0x00ffffff) | (*(char *)p << 24), p);
return 0;
}
#endif /* __H8300_FLAT_H__ */ #endif /* __H8300_FLAT_H__ */
...@@ -87,42 +87,6 @@ static inline int __access_ok(const void __user *p, unsigned long size) ...@@ -87,42 +87,6 @@ static inline int __access_ok(const void __user *p, unsigned long size)
#define __put_user(x, ptr) __put_user_nocheck((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr))) #define __put_user(x, ptr) __put_user_nocheck((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr)))
#define __get_user(x, ptr) __get_user_nocheck((x), (ptr), sizeof(*(ptr))) #define __get_user(x, ptr) __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
extern long __put_user_unaligned_unknown (void);
#define __put_user_unaligned(x, ptr) \
({ \
long __ret; \
switch (sizeof(*(ptr))) { \
case 1: __ret = __put_user((x), (ptr)); break; \
case 2: __ret = (__put_user((x), (u8 __user *)(ptr))) \
| (__put_user((x) >> 8, ((u8 __user *)(ptr) + 1))); break; \
case 4: __ret = (__put_user((x), (u16 __user *)(ptr))) \
| (__put_user((x) >> 16, ((u16 __user *)(ptr) + 1))); break; \
case 8: __ret = (__put_user((x), (u32 __user *)(ptr))) \
| (__put_user((x) >> 32, ((u32 __user *)(ptr) + 1))); break; \
default: __ret = __put_user_unaligned_unknown(); \
} \
__ret; \
})
extern long __get_user_unaligned_unknown (void);
#define __get_user_unaligned(x, ptr) \
({ \
long __ret; \
switch (sizeof(*(ptr))) { \
case 1: __ret = __get_user((x), (ptr)); break; \
case 2: __ret = (__get_user((x), (u8 __user *)(ptr))) \
| (__get_user((x) >> 8, ((u8 __user *)(ptr) + 1))); break; \
case 4: __ret = (__get_user((x), (u16 __user *)(ptr))) \
| (__get_user((x) >> 16, ((u16 __user *)(ptr) + 1))); break; \
case 8: __ret = (__get_user((x), (u32 __user *)(ptr))) \
| (__get_user((x) >> 32, ((u32 __user *)(ptr) + 1))); break; \
default: __ret = __get_user_unaligned_unknown(); \
} \
__ret; \
})
#ifdef ASM_SUPPORTED #ifdef ASM_SUPPORTED
struct __large_struct { unsigned long buf[100]; }; struct __large_struct { unsigned long buf[100]; };
# define __m(x) (*(struct __large_struct __user *)(x)) # define __m(x) (*(struct __large_struct __user *)(x))
......
...@@ -17,11 +17,6 @@ ...@@ -17,11 +17,6 @@
#define flat_set_persistent(relval, p) 0 #define flat_set_persistent(relval, p) 0
#define flat_reloc_valid(reloc, size) \ #define flat_reloc_valid(reloc, size) \
(((reloc) - textlen_for_m32r_lo16_data) <= (size)) (((reloc) - textlen_for_m32r_lo16_data) <= (size))
#define flat_get_addr_from_rp(rp, relval, flags, persistent) \
m32r_flat_get_addr_from_rp(rp, relval, (text_len) )
#define flat_put_addr_at_rp(rp, addr, relval) \
m32r_flat_put_addr_at_rp(rp, addr, relval)
/* Convert a relocation entry into an address. */ /* Convert a relocation entry into an address. */
static inline unsigned long static inline unsigned long
...@@ -57,9 +52,9 @@ flat_get_relocate_addr (unsigned long relval) ...@@ -57,9 +52,9 @@ flat_get_relocate_addr (unsigned long relval)
static unsigned long textlen_for_m32r_lo16_data = 0; static unsigned long textlen_for_m32r_lo16_data = 0;
static inline unsigned long m32r_flat_get_addr_from_rp (unsigned long *rp, static inline unsigned long m32r_flat_get_addr_from_rp (u32 *rp,
unsigned long relval, u32 relval,
unsigned long textlen) u32 textlen)
{ {
unsigned int reloc = flat_m32r_get_reloc_type (relval); unsigned int reloc = flat_m32r_get_reloc_type (relval);
textlen_for_m32r_lo16_data = 0; textlen_for_m32r_lo16_data = 0;
...@@ -100,9 +95,7 @@ static inline unsigned long m32r_flat_get_addr_from_rp (unsigned long *rp, ...@@ -100,9 +95,7 @@ static inline unsigned long m32r_flat_get_addr_from_rp (unsigned long *rp,
return ~0; /* bogus value */ return ~0; /* bogus value */
} }
static inline void m32r_flat_put_addr_at_rp (unsigned long *rp, static inline void flat_put_addr_at_rp(u32 *rp, u32 addr, u32 relval)
unsigned long addr,
unsigned long relval)
{ {
unsigned int reloc = flat_m32r_get_reloc_type (relval); unsigned int reloc = flat_m32r_get_reloc_type (relval);
if (reloc & 0xf0) { if (reloc & 0xf0) {
...@@ -142,4 +135,8 @@ static inline void m32r_flat_put_addr_at_rp (unsigned long *rp, ...@@ -142,4 +135,8 @@ static inline void m32r_flat_put_addr_at_rp (unsigned long *rp,
} }
} }
// kludge - text_len is a local variable in the only user.
#define flat_get_addr_from_rp(rp, relval, flags, addr, persistent) \
(m32r_flat_get_addr_from_rp(rp, relval, text_len), 0)
#endif /* __ASM_M32R_FLAT_H */ #endif /* __ASM_M32R_FLAT_H */
...@@ -5,12 +5,29 @@ ...@@ -5,12 +5,29 @@
#ifndef __M68KNOMMU_FLAT_H__ #ifndef __M68KNOMMU_FLAT_H__
#define __M68KNOMMU_FLAT_H__ #define __M68KNOMMU_FLAT_H__
#include <linux/uaccess.h>
#define flat_argvp_envp_on_stack() 1 #define flat_argvp_envp_on_stack() 1
#define flat_old_ram_flag(flags) (flags) #define flat_old_ram_flag(flags) (flags)
#define flat_reloc_valid(reloc, size) ((reloc) <= (size)) #define flat_reloc_valid(reloc, size) ((reloc) <= (size))
#define flat_get_addr_from_rp(rp, relval, flags, p) \ static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
({ unsigned long __val; __get_user_unaligned(__val, rp); __val; }) u32 *addr, u32 *persistent)
#define flat_put_addr_at_rp(rp, val, relval) __put_user_unaligned(val, rp) {
#ifdef CONFIG_CPU_HAS_NO_UNALIGNED
return copy_from_user(addr, rp, 4) ? -EFAULT : 0;
#else
return get_user(*addr, rp);
#endif
}
static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
{
#ifdef CONFIG_CPU_HAS_NO_UNALIGNED
return copy_to_user(rp, &addr, 4) ? -EFAULT : 0;
#else
return put_user(addr, rp);
#endif
}
#define flat_get_relocate_addr(rel) (rel) #define flat_get_relocate_addr(rel) (rel)
static inline int flat_set_persistent(unsigned long relval, static inline int flat_set_persistent(unsigned long relval,
......
...@@ -3,11 +3,4 @@ ...@@ -3,11 +3,4 @@
#else #else
#include <asm/uaccess_mm.h> #include <asm/uaccess_mm.h>
#endif #endif
#include <asm/extable.h> #include <asm/extable.h>
#ifdef CONFIG_CPU_HAS_NO_UNALIGNED
#include <asm-generic/uaccess-unaligned.h>
#else
#define __get_user_unaligned(x, ptr) __get_user((x), (ptr))
#define __put_user_unaligned(x, ptr) __put_user((x), (ptr))
#endif
...@@ -32,29 +32,27 @@ ...@@ -32,29 +32,27 @@
* reference * reference
*/ */
static inline unsigned long static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
flat_get_addr_from_rp(unsigned long *rp, unsigned long relval, u32 *addr, u32 *persistent)
unsigned long flags, unsigned long *persistent)
{ {
unsigned long addr; u32 *p = (__force u32 *)rp;
(void)flags;
/* Is it a split 64/32 reference? */ /* Is it a split 64/32 reference? */
if (relval & 0x80000000) { if (relval & 0x80000000) {
/* Grab the two halves of the reference */ /* Grab the two halves of the reference */
unsigned long val_hi, val_lo; u32 val_hi, val_lo;
val_hi = get_unaligned(rp); val_hi = get_unaligned(p);
val_lo = get_unaligned(rp+1); val_lo = get_unaligned(p+1);
/* Crack the address out */ /* Crack the address out */
addr = ((val_hi & 0xffff) << 16) + (val_lo & 0xffff); *addr = ((val_hi & 0xffff) << 16) + (val_lo & 0xffff);
} else { } else {
/* Get the address straight out */ /* Get the address straight out */
addr = get_unaligned(rp); *addr = get_unaligned(p);
} }
return addr; return 0;
} }
/* /*
...@@ -63,25 +61,27 @@ flat_get_addr_from_rp(unsigned long *rp, unsigned long relval, ...@@ -63,25 +61,27 @@ flat_get_addr_from_rp(unsigned long *rp, unsigned long relval,
*/ */
static inline void static inline void
flat_put_addr_at_rp(unsigned long *rp, unsigned long addr, unsigned long relval) flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 relval)
{ {
u32 *p = (__force u32 *)rp;
/* Is this a split 64/32 reloc? */ /* Is this a split 64/32 reloc? */
if (relval & 0x80000000) { if (relval & 0x80000000) {
/* Get the two "halves" */ /* Get the two "halves" */
unsigned long val_hi = get_unaligned(rp); unsigned long val_hi = get_unaligned(p);
unsigned long val_lo = get_unaligned(rp + 1); unsigned long val_lo = get_unaligned(p + 1);
/* insert the address */ /* insert the address */
val_hi = (val_hi & 0xffff0000) | addr >> 16; val_hi = (val_hi & 0xffff0000) | addr >> 16;
val_lo = (val_lo & 0xffff0000) | (addr & 0xffff); val_lo = (val_lo & 0xffff0000) | (addr & 0xffff);
/* store the two halves back into memory */ /* store the two halves back into memory */
put_unaligned(val_hi, rp); put_unaligned(val_hi, p);
put_unaligned(val_lo, rp+1); put_unaligned(val_lo, p+1);
} else { } else {
/* Put it straight in, no messing around */ /* Put it straight in, no messing around */
put_unaligned(addr, rp); put_unaligned(addr, p);
} }
return 0;
} }
#define flat_get_relocate_addr(rel) (rel & 0x7fffffff) #define flat_get_relocate_addr(rel) (rel & 0x7fffffff)
......
...@@ -496,283 +496,6 @@ do { \ ...@@ -496,283 +496,6 @@ do { \
extern void __put_user_unknown(void); extern void __put_user_unknown(void);
/*
* ul{b,h,w} are macros and there are no equivalent macros for EVA.
* EVA unaligned access is handled in the ADE exception handler.
*/
#ifndef CONFIG_EVA
/*
* put_user_unaligned: - Write a simple value into user space.
* @x: Value to copy to user space.
* @ptr: Destination address, in user space.
*
* Context: User context only. This function may sleep if pagefaults are
* enabled.
*
* This macro copies a single simple value from kernel space to user
* space. It supports simple types like char and int, but not larger
* data types like structures or arrays.
*
* @ptr must have pointer-to-simple-variable type, and @x must be assignable
* to the result of dereferencing @ptr.
*
* Returns zero on success, or -EFAULT on error.
*/
#define put_user_unaligned(x,ptr) \
__put_user_unaligned_check((x),(ptr),sizeof(*(ptr)))
/*
* get_user_unaligned: - Get a simple variable from user space.
* @x: Variable to store result.
* @ptr: Source address, in user space.
*
* Context: User context only. This function may sleep if pagefaults are
* enabled.
*
* This macro copies a single simple variable from user space to kernel
* space. It supports simple types like char and int, but not larger
* data types like structures or arrays.
*
* @ptr must have pointer-to-simple-variable type, and the result of
* dereferencing @ptr must be assignable to @x without a cast.
*
* Returns zero on success, or -EFAULT on error.
* On error, the variable @x is set to zero.
*/
#define get_user_unaligned(x,ptr) \
__get_user_unaligned_check((x),(ptr),sizeof(*(ptr)))
/*
* __put_user_unaligned: - Write a simple value into user space, with less checking.
* @x: Value to copy to user space.
* @ptr: Destination address, in user space.
*
* Context: User context only. This function may sleep if pagefaults are
* enabled.
*
* This macro copies a single simple value from kernel space to user
* space. It supports simple types like char and int, but not larger
* data types like structures or arrays.
*
* @ptr must have pointer-to-simple-variable type, and @x must be assignable
* to the result of dereferencing @ptr.
*
* Caller must check the pointer with access_ok() before calling this
* function.
*
* Returns zero on success, or -EFAULT on error.
*/
#define __put_user_unaligned(x,ptr) \
__put_user_unaligned_nocheck((x),(ptr),sizeof(*(ptr)))
/*
* __get_user_unaligned: - Get a simple variable from user space, with less checking.
* @x: Variable to store result.
* @ptr: Source address, in user space.
*
* Context: User context only. This function may sleep if pagefaults are
* enabled.
*
* This macro copies a single simple variable from user space to kernel
* space. It supports simple types like char and int, but not larger
* data types like structures or arrays.
*
* @ptr must have pointer-to-simple-variable type, and the result of
* dereferencing @ptr must be assignable to @x without a cast.
*
* Caller must check the pointer with access_ok() before calling this
* function.
*
* Returns zero on success, or -EFAULT on error.
* On error, the variable @x is set to zero.
*/
#define __get_user_unaligned(x,ptr) \
__get_user_unaligned_nocheck((x),(ptr),sizeof(*(ptr)))
/*
* Yuck. We need two variants, one for 64bit operation and one
* for 32 bit mode and old iron.
*/
#ifdef CONFIG_32BIT
#define __GET_USER_UNALIGNED_DW(val, ptr) \
__get_user_unaligned_asm_ll32(val, ptr)
#endif
#ifdef CONFIG_64BIT
#define __GET_USER_UNALIGNED_DW(val, ptr) \
__get_user_unaligned_asm(val, "uld", ptr)
#endif
extern void __get_user_unaligned_unknown(void);
#define __get_user_unaligned_common(val, size, ptr) \
do { \
switch (size) { \
case 1: __get_data_asm(val, "lb", ptr); break; \
case 2: __get_data_unaligned_asm(val, "ulh", ptr); break; \
case 4: __get_data_unaligned_asm(val, "ulw", ptr); break; \
case 8: __GET_USER_UNALIGNED_DW(val, ptr); break; \
default: __get_user_unaligned_unknown(); break; \
} \
} while (0)
#define __get_user_unaligned_nocheck(x,ptr,size) \
({ \
int __gu_err; \
\
__get_user_unaligned_common((x), size, ptr); \
__gu_err; \
})
#define __get_user_unaligned_check(x,ptr,size) \
({ \
int __gu_err = -EFAULT; \
const __typeof__(*(ptr)) __user * __gu_ptr = (ptr); \
\
if (likely(access_ok(VERIFY_READ, __gu_ptr, size))) \
__get_user_unaligned_common((x), size, __gu_ptr); \
\
__gu_err; \
})
#define __get_data_unaligned_asm(val, insn, addr) \
{ \
long __gu_tmp; \
\
__asm__ __volatile__( \
"1: " insn " %1, %3 \n" \
"2: \n" \
" .insn \n" \
" .section .fixup,\"ax\" \n" \
"3: li %0, %4 \n" \
" move %1, $0 \n" \
" j 2b \n" \
" .previous \n" \
" .section __ex_table,\"a\" \n" \
" "__UA_ADDR "\t1b, 3b \n" \
" "__UA_ADDR "\t1b + 4, 3b \n" \
" .previous \n" \
: "=r" (__gu_err), "=r" (__gu_tmp) \
: "0" (0), "o" (__m(addr)), "i" (-EFAULT)); \
\
(val) = (__typeof__(*(addr))) __gu_tmp; \
}
/*
* Get a long long 64 using 32 bit registers.
*/
#define __get_user_unaligned_asm_ll32(val, addr) \
{ \
unsigned long long __gu_tmp; \
\
__asm__ __volatile__( \
"1: ulw %1, (%3) \n" \
"2: ulw %D1, 4(%3) \n" \
" move %0, $0 \n" \
"3: \n" \
" .insn \n" \
" .section .fixup,\"ax\" \n" \
"4: li %0, %4 \n" \
" move %1, $0 \n" \
" move %D1, $0 \n" \
" j 3b \n" \
" .previous \n" \
" .section __ex_table,\"a\" \n" \
" " __UA_ADDR " 1b, 4b \n" \
" " __UA_ADDR " 1b + 4, 4b \n" \
" " __UA_ADDR " 2b, 4b \n" \
" " __UA_ADDR " 2b + 4, 4b \n" \
" .previous \n" \
: "=r" (__gu_err), "=&r" (__gu_tmp) \
: "0" (0), "r" (addr), "i" (-EFAULT)); \
(val) = (__typeof__(*(addr))) __gu_tmp; \
}
/*
* Yuck. We need two variants, one for 64bit operation and one
* for 32 bit mode and old iron.
*/
#ifdef CONFIG_32BIT
#define __PUT_USER_UNALIGNED_DW(ptr) __put_user_unaligned_asm_ll32(ptr)
#endif
#ifdef CONFIG_64BIT
#define __PUT_USER_UNALIGNED_DW(ptr) __put_user_unaligned_asm("usd", ptr)
#endif
#define __put_user_unaligned_common(ptr, size) \
do { \
switch (size) { \
case 1: __put_data_asm("sb", ptr); break; \
case 2: __put_user_unaligned_asm("ush", ptr); break; \
case 4: __put_user_unaligned_asm("usw", ptr); break; \
case 8: __PUT_USER_UNALIGNED_DW(ptr); break; \
default: __put_user_unaligned_unknown(); break; \
} while (0)
#define __put_user_unaligned_nocheck(x,ptr,size) \
({ \
__typeof__(*(ptr)) __pu_val; \
int __pu_err = 0; \
\
__pu_val = (x); \
__put_user_unaligned_common(ptr, size); \
__pu_err; \
})
#define __put_user_unaligned_check(x,ptr,size) \
({ \
__typeof__(*(ptr)) __user *__pu_addr = (ptr); \
__typeof__(*(ptr)) __pu_val = (x); \
int __pu_err = -EFAULT; \
\
if (likely(access_ok(VERIFY_WRITE, __pu_addr, size))) \
__put_user_unaligned_common(__pu_addr, size); \
\
__pu_err; \
})
#define __put_user_unaligned_asm(insn, ptr) \
{ \
__asm__ __volatile__( \
"1: " insn " %z2, %3 # __put_user_unaligned_asm\n" \
"2: \n" \
" .insn \n" \
" .section .fixup,\"ax\" \n" \
"3: li %0, %4 \n" \
" j 2b \n" \
" .previous \n" \
" .section __ex_table,\"a\" \n" \
" " __UA_ADDR " 1b, 3b \n" \
" .previous \n" \
: "=r" (__pu_err) \
: "0" (0), "Jr" (__pu_val), "o" (__m(ptr)), \
"i" (-EFAULT)); \
}
#define __put_user_unaligned_asm_ll32(ptr) \
{ \
__asm__ __volatile__( \
"1: sw %2, (%3) # __put_user_unaligned_asm_ll32 \n" \
"2: sw %D2, 4(%3) \n" \
"3: \n" \
" .insn \n" \
" .section .fixup,\"ax\" \n" \
"4: li %0, %4 \n" \
" j 3b \n" \
" .previous \n" \
" .section __ex_table,\"a\" \n" \
" " __UA_ADDR " 1b, 4b \n" \
" " __UA_ADDR " 1b + 4, 4b \n" \
" " __UA_ADDR " 2b, 4b \n" \
" " __UA_ADDR " 2b + 4, 4b \n" \
" .previous" \
: "=r" (__pu_err) \
: "0" (0), "r" (__pu_val), "r" (ptr), \
"i" (-EFAULT)); \
}
extern void __put_user_unaligned_unknown(void);
#endif
/* /*
* We're generating jump to subroutines which will be outside the range of * We're generating jump to subroutines which will be outside the range of
* jump instructions * jump instructions
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
*/ */
#include <asm/page.h> #include <asm/page.h>
#include <asm/cache.h> #include <asm/cache.h>
#include <asm-generic/uaccess-unaligned.h>
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/string.h> #include <linux/string.h>
......
...@@ -90,9 +90,6 @@ ...@@ -90,9 +90,6 @@
#define __put_user_inatomic(x, ptr) \ #define __put_user_inatomic(x, ptr) \
__put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) __put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
#define __get_user_unaligned __get_user
#define __put_user_unaligned __put_user
extern long __put_user_bad(void); extern long __put_user_bad(void);
/* /*
......
...@@ -249,9 +249,6 @@ int __put_user_bad(void) __attribute__((noreturn)); ...@@ -249,9 +249,6 @@ int __put_user_bad(void) __attribute__((noreturn));
int __get_user_bad(void) __attribute__((noreturn)); int __get_user_bad(void) __attribute__((noreturn));
#define __put_user_unaligned __put_user
#define __get_user_unaligned __get_user
unsigned long __must_check unsigned long __must_check
raw_copy_in_user(void __user *to, const void __user *from, unsigned long n); raw_copy_in_user(void __user *to, const void __user *from, unsigned long n);
......
...@@ -12,11 +12,22 @@ ...@@ -12,11 +12,22 @@
#ifndef __ASM_SH_FLAT_H #ifndef __ASM_SH_FLAT_H
#define __ASM_SH_FLAT_H #define __ASM_SH_FLAT_H
#include <asm/unaligned.h>
#define flat_argvp_envp_on_stack() 0 #define flat_argvp_envp_on_stack() 0
#define flat_old_ram_flag(flags) (flags) #define flat_old_ram_flag(flags) (flags)
#define flat_reloc_valid(reloc, size) ((reloc) <= (size)) #define flat_reloc_valid(reloc, size) ((reloc) <= (size))
#define flat_get_addr_from_rp(rp, relval, flags, p) get_unaligned(rp) static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
#define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp) u32 *addr, u32 *persistent)
{
*addr = get_unaligned((__force u32 *)rp);
return 0;
}
static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
{
put_unaligned(addr, (__force u32 *)rp);
return 0;
}
#define flat_get_relocate_addr(rel) (rel) #define flat_get_relocate_addr(rel) (rel)
#define flat_set_persistent(relval, p) ({ (void)p; 0; }) #define flat_set_persistent(relval, p) ({ (void)p; 0; })
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include <linux/string.h> #include <linux/string.h>
#include <asm/asi.h> #include <asm/asi.h>
#include <asm/spitfire.h> #include <asm/spitfire.h>
#include <asm-generic/uaccess-unaligned.h>
#include <asm/extable_64.h> #include <asm/extable_64.h>
#include <asm/processor.h> #include <asm/processor.h>
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
* User space memory access functions * User space memory access functions
*/ */
#include <linux/mm.h> #include <linux/mm.h>
#include <asm-generic/uaccess-unaligned.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/page.h> #include <asm/page.h>
......
...@@ -535,9 +535,6 @@ struct __large_struct { unsigned long buf[100]; }; ...@@ -535,9 +535,6 @@ struct __large_struct { unsigned long buf[100]; };
#define __put_user(x, ptr) \ #define __put_user(x, ptr) \
__put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
#define __get_user_unaligned __get_user
#define __put_user_unaligned __put_user
/* /*
* {get|put}_user_try and catch * {get|put}_user_try and catch
* *
......
#ifndef __ASM_XTENSA_FLAT_H #ifndef __ASM_XTENSA_FLAT_H
#define __ASM_XTENSA_FLAT_H #define __ASM_XTENSA_FLAT_H
#include <asm/unaligned.h>
#define flat_argvp_envp_on_stack() 0 #define flat_argvp_envp_on_stack() 0
#define flat_old_ram_flag(flags) (flags) #define flat_old_ram_flag(flags) (flags)
#define flat_reloc_valid(reloc, size) ((reloc) <= (size)) #define flat_reloc_valid(reloc, size) ((reloc) <= (size))
#define flat_get_addr_from_rp(rp, relval, flags, p) get_unaligned(rp) static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
#define flat_put_addr_at_rp(rp, val, relval ) put_unaligned(val, rp) u32 *addr, u32 *persistent)
{
*addr = get_unaligned((__force u32 *)rp);
return 0;
}
static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
{
put_unaligned(addr, (__force u32 *)rp);
return 0;
}
#define flat_get_relocate_addr(rel) (rel) #define flat_get_relocate_addr(rel) (rel)
#define flat_set_persistent(relval, p) 0 #define flat_set_persistent(relval, p) 0
......
...@@ -422,9 +422,9 @@ static int load_flat_file(struct linux_binprm *bprm, ...@@ -422,9 +422,9 @@ static int load_flat_file(struct linux_binprm *bprm,
{ {
struct flat_hdr *hdr; struct flat_hdr *hdr;
unsigned long textpos, datapos, realdatastart; unsigned long textpos, datapos, realdatastart;
unsigned long text_len, data_len, bss_len, stack_len, full_data, flags; u32 text_len, data_len, bss_len, stack_len, full_data, flags;
unsigned long len, memp, memp_size, extra, rlim; unsigned long len, memp, memp_size, extra, rlim;
unsigned long __user *reloc, *rp; u32 __user *reloc, *rp;
struct inode *inode; struct inode *inode;
int i, rev, relocs; int i, rev, relocs;
loff_t fpos; loff_t fpos;
...@@ -596,13 +596,13 @@ static int load_flat_file(struct linux_binprm *bprm, ...@@ -596,13 +596,13 @@ static int load_flat_file(struct linux_binprm *bprm,
goto err; goto err;
} }
reloc = (unsigned long __user *) reloc = (u32 __user *)
(datapos + (ntohl(hdr->reloc_start) - text_len)); (datapos + (ntohl(hdr->reloc_start) - text_len));
memp = realdatastart; memp = realdatastart;
memp_size = len; memp_size = len;
} else { } else {
len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(u32);
len = PAGE_ALIGN(len); len = PAGE_ALIGN(len);
textpos = vm_mmap(NULL, 0, len, textpos = vm_mmap(NULL, 0, len,
PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
...@@ -618,10 +618,10 @@ static int load_flat_file(struct linux_binprm *bprm, ...@@ -618,10 +618,10 @@ static int load_flat_file(struct linux_binprm *bprm,
realdatastart = textpos + ntohl(hdr->data_start); realdatastart = textpos + ntohl(hdr->data_start);
datapos = ALIGN(realdatastart + datapos = ALIGN(realdatastart +
MAX_SHARED_LIBS * sizeof(unsigned long), MAX_SHARED_LIBS * sizeof(u32),
FLAT_DATA_ALIGN); FLAT_DATA_ALIGN);
reloc = (unsigned long __user *) reloc = (u32 __user *)
(datapos + (ntohl(hdr->reloc_start) - text_len)); (datapos + (ntohl(hdr->reloc_start) - text_len));
memp = textpos; memp = textpos;
memp_size = len; memp_size = len;
...@@ -694,7 +694,7 @@ static int load_flat_file(struct linux_binprm *bprm, ...@@ -694,7 +694,7 @@ static int load_flat_file(struct linux_binprm *bprm,
ret = result; ret = result;
pr_err("Unable to read code+data+bss, errno %d\n", ret); pr_err("Unable to read code+data+bss, errno %d\n", ret);
vm_munmap(textpos, text_len + data_len + extra + vm_munmap(textpos, text_len + data_len + extra +
MAX_SHARED_LIBS * sizeof(unsigned long)); MAX_SHARED_LIBS * sizeof(u32));
goto err; goto err;
} }
} }
...@@ -754,8 +754,8 @@ static int load_flat_file(struct linux_binprm *bprm, ...@@ -754,8 +754,8 @@ static int load_flat_file(struct linux_binprm *bprm,
* image. * image.
*/ */
if (flags & FLAT_FLAG_GOTPIC) { if (flags & FLAT_FLAG_GOTPIC) {
for (rp = (unsigned long __user *)datapos; ; rp++) { for (rp = (u32 __user *)datapos; ; rp++) {
unsigned long addr, rp_val; u32 addr, rp_val;
if (get_user(rp_val, rp)) if (get_user(rp_val, rp))
return -EFAULT; return -EFAULT;
if (rp_val == 0xffffffff) if (rp_val == 0xffffffff)
...@@ -784,9 +784,9 @@ static int load_flat_file(struct linux_binprm *bprm, ...@@ -784,9 +784,9 @@ static int load_flat_file(struct linux_binprm *bprm,
* __start to address 4 so that is okay). * __start to address 4 so that is okay).
*/ */
if (rev > OLD_FLAT_VERSION) { if (rev > OLD_FLAT_VERSION) {
unsigned long __maybe_unused persistent = 0; u32 __maybe_unused persistent = 0;
for (i = 0; i < relocs; i++) { for (i = 0; i < relocs; i++) {
unsigned long addr, relval; u32 addr, relval;
/* /*
* Get the address of the pointer to be * Get the address of the pointer to be
...@@ -799,15 +799,18 @@ static int load_flat_file(struct linux_binprm *bprm, ...@@ -799,15 +799,18 @@ static int load_flat_file(struct linux_binprm *bprm,
if (flat_set_persistent(relval, &persistent)) if (flat_set_persistent(relval, &persistent))
continue; continue;
addr = flat_get_relocate_addr(relval); addr = flat_get_relocate_addr(relval);
rp = (unsigned long __user *)calc_reloc(addr, libinfo, id, 1); rp = (u32 __user *)calc_reloc(addr, libinfo, id, 1);
if (rp == (unsigned long __user *)RELOC_FAILED) { if (rp == (u32 __user *)RELOC_FAILED) {
ret = -ENOEXEC; ret = -ENOEXEC;
goto err; goto err;
} }
/* Get the pointer's value. */ /* Get the pointer's value. */
addr = flat_get_addr_from_rp(rp, relval, flags, ret = flat_get_addr_from_rp(rp, relval, flags,
&persistent); &addr, &persistent);
if (unlikely(ret))
goto err;
if (addr != 0) { if (addr != 0) {
/* /*
* Do the relocation. PIC relocs in the data section are * Do the relocation. PIC relocs in the data section are
...@@ -822,12 +825,14 @@ static int load_flat_file(struct linux_binprm *bprm, ...@@ -822,12 +825,14 @@ static int load_flat_file(struct linux_binprm *bprm,
} }
/* Write back the relocated pointer. */ /* Write back the relocated pointer. */
flat_put_addr_at_rp(rp, addr, relval); ret = flat_put_addr_at_rp(rp, addr, relval);
if (unlikely(ret))
goto err;
} }
} }
} else { } else {
for (i = 0; i < relocs; i++) { for (i = 0; i < relocs; i++) {
unsigned long relval; u32 relval;
if (get_user(relval, reloc + i)) if (get_user(relval, reloc + i))
return -EFAULT; return -EFAULT;
relval = ntohl(relval); relval = ntohl(relval);
......
#ifndef __ASM_GENERIC_UACCESS_UNALIGNED_H
#define __ASM_GENERIC_UACCESS_UNALIGNED_H
/*
* This macro should be used instead of __get_user() when accessing
* values at locations that are not known to be aligned.
*/
#define __get_user_unaligned(x, ptr) \
({ \
__typeof__ (*(ptr)) __x; \
__copy_from_user(&__x, (ptr), sizeof(*(ptr))) ? -EFAULT : 0; \
(x) = __x; \
})
/*
* This macro should be used instead of __put_user() when accessing
* values at locations that are not known to be aligned.
*/
#define __put_user_unaligned(x, ptr) \
({ \
__typeof__ (*(ptr)) __x = (x); \
__copy_to_user((ptr), &__x, sizeof(*(ptr))) ? -EFAULT : 0; \
})
#endif /* __ASM_GENERIC_UACCESS_UNALIGNED_H */
...@@ -9,8 +9,8 @@ ...@@ -9,8 +9,8 @@
#ifndef _LINUX_FLAT_H #ifndef _LINUX_FLAT_H
#define _LINUX_FLAT_H #define _LINUX_FLAT_H
#include <asm/flat.h>
#include <uapi/linux/flat.h> #include <uapi/linux/flat.h>
#include <asm/flat.h>
/* /*
* While it would be nice to keep this header clean, users of older * While it would be nice to keep this header clean, users of older
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment