mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	binfmt_flat: flat_{get,put}_addr_from_rp() should be able to fail
on MMU targets EFAULT is possible here. Make both return 0 or error, passing what used to be the return value of flat_get_addr_from_rp() by reference. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
		
							parent
							
								
									2ea659a9ef
								
							
						
					
					
						commit
						468138d785
					
				
					 12 changed files with 168 additions and 81 deletions
				
			
		|  | @ -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 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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 @@ | ||||||
| #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); | ||||||
|  * 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; | ||||||
|  |  | ||||||
|  | @ -1,11 +1,22 @@ | ||||||
| #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 @@ | ||||||
| #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 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #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__ */ | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
| 
 | 
 | ||||||
| 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, | ||||||
| 	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, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // 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 @@ | ||||||
| #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, | ||||||
|  |  | ||||||
|  | @ -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, | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| 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) | ||||||
|  |  | ||||||
|  | @ -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; }) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,11 +1,22 @@ | ||||||
| #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, | ||||||
| { | { | ||||||
| 	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, | ||||||
| 			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, | ||||||
| 
 | 
 | ||||||
| 		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, | ||||||
| 			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, | ||||||
| 	 * 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, | ||||||
| 	 * __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, | ||||||
| 			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, | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				/* 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); | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Al Viro
						Al Viro