forked from mirrors/linux
		
	mips: sanitize __access_ok()
for one thing, the last argument is always __access_mask and had been such since 2.4.0-test3pre8; for another, it can bloody well be a static inline - -O2 or -Os, __builtin_constant_p() propagates through static inline calls. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
		
							parent
							
								
									054838bc01
								
							
						
					
					
						commit
						f0a955f4ee
					
				
					 4 changed files with 20 additions and 29 deletions
				
			
		|  | @ -128,23 +128,14 @@ static inline bool eva_kernel_access(void) | |||
|  * this function, memory access functions may still return -EFAULT. | ||||
|  */ | ||||
| 
 | ||||
| #define __access_mask get_fs().seg | ||||
| 
 | ||||
| #define __access_ok(addr, size, mask)					\ | ||||
| ({									\ | ||||
| 	unsigned long __addr = (unsigned long) (addr);			\ | ||||
| 	unsigned long __size = size;					\ | ||||
| 	unsigned long __mask = mask;					\ | ||||
| 	unsigned long __ok;						\ | ||||
| 									\ | ||||
| 	__chk_user_ptr(addr);						\ | ||||
| 	__ok = (signed long)(__mask & (__addr | (__addr + __size) |	\ | ||||
| 		__ua_size(__size)));					\ | ||||
| 	__ok == 0;							\ | ||||
| }) | ||||
| static inline int __access_ok(const void __user *p, unsigned long size) | ||||
| { | ||||
| 	unsigned long addr = (unsigned long)p; | ||||
| 	return (get_fs().seg & (addr | (addr + size) | __ua_size(size))) == 0; | ||||
| } | ||||
| 
 | ||||
| #define access_ok(type, addr, size)					\ | ||||
| 	likely(__access_ok((addr), (size), __access_mask)) | ||||
| 	likely(__access_ok((addr), (size))) | ||||
| 
 | ||||
| /*
 | ||||
|  * put_user: - Write a simple value into user space. | ||||
|  |  | |||
|  | @ -1200,7 +1200,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) | |||
| 	case lwl_op: | ||||
| 		rt = regs->regs[MIPSInst_RT(inst)]; | ||||
| 		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst); | ||||
| 		if (!access_ok(VERIFY_READ, vaddr, 4)) { | ||||
| 		if (!access_ok(VERIFY_READ, (void __user *)vaddr, 4)) { | ||||
| 			current->thread.cp0_baduaddr = vaddr; | ||||
| 			err = SIGSEGV; | ||||
| 			break; | ||||
|  | @ -1273,7 +1273,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) | |||
| 	case lwr_op: | ||||
| 		rt = regs->regs[MIPSInst_RT(inst)]; | ||||
| 		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst); | ||||
| 		if (!access_ok(VERIFY_READ, vaddr, 4)) { | ||||
| 		if (!access_ok(VERIFY_READ, (void __user *)vaddr, 4)) { | ||||
| 			current->thread.cp0_baduaddr = vaddr; | ||||
| 			err = SIGSEGV; | ||||
| 			break; | ||||
|  | @ -1347,7 +1347,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) | |||
| 	case swl_op: | ||||
| 		rt = regs->regs[MIPSInst_RT(inst)]; | ||||
| 		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst); | ||||
| 		if (!access_ok(VERIFY_WRITE, vaddr, 4)) { | ||||
| 		if (!access_ok(VERIFY_WRITE, (void __user *)vaddr, 4)) { | ||||
| 			current->thread.cp0_baduaddr = vaddr; | ||||
| 			err = SIGSEGV; | ||||
| 			break; | ||||
|  | @ -1417,7 +1417,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) | |||
| 	case swr_op: | ||||
| 		rt = regs->regs[MIPSInst_RT(inst)]; | ||||
| 		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst); | ||||
| 		if (!access_ok(VERIFY_WRITE, vaddr, 4)) { | ||||
| 		if (!access_ok(VERIFY_WRITE, (void __user *)vaddr, 4)) { | ||||
| 			current->thread.cp0_baduaddr = vaddr; | ||||
| 			err = SIGSEGV; | ||||
| 			break; | ||||
|  | @ -1492,7 +1492,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) | |||
| 
 | ||||
| 		rt = regs->regs[MIPSInst_RT(inst)]; | ||||
| 		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst); | ||||
| 		if (!access_ok(VERIFY_READ, vaddr, 8)) { | ||||
| 		if (!access_ok(VERIFY_READ, (void __user *)vaddr, 8)) { | ||||
| 			current->thread.cp0_baduaddr = vaddr; | ||||
| 			err = SIGSEGV; | ||||
| 			break; | ||||
|  | @ -1611,7 +1611,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) | |||
| 
 | ||||
| 		rt = regs->regs[MIPSInst_RT(inst)]; | ||||
| 		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst); | ||||
| 		if (!access_ok(VERIFY_READ, vaddr, 8)) { | ||||
| 		if (!access_ok(VERIFY_READ, (void __user *)vaddr, 8)) { | ||||
| 			current->thread.cp0_baduaddr = vaddr; | ||||
| 			err = SIGSEGV; | ||||
| 			break; | ||||
|  | @ -1730,7 +1730,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) | |||
| 
 | ||||
| 		rt = regs->regs[MIPSInst_RT(inst)]; | ||||
| 		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst); | ||||
| 		if (!access_ok(VERIFY_WRITE, vaddr, 8)) { | ||||
| 		if (!access_ok(VERIFY_WRITE, (void __user *)vaddr, 8)) { | ||||
| 			current->thread.cp0_baduaddr = vaddr; | ||||
| 			err = SIGSEGV; | ||||
| 			break; | ||||
|  | @ -1848,7 +1848,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) | |||
| 
 | ||||
| 		rt = regs->regs[MIPSInst_RT(inst)]; | ||||
| 		vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(inst); | ||||
| 		if (!access_ok(VERIFY_WRITE, vaddr, 8)) { | ||||
| 		if (!access_ok(VERIFY_WRITE, (void __user *)vaddr, 8)) { | ||||
| 			current->thread.cp0_baduaddr = vaddr; | ||||
| 			err = SIGSEGV; | ||||
| 			break; | ||||
|  | @ -1965,7 +1965,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) | |||
| 			err = SIGBUS; | ||||
| 			break; | ||||
| 		} | ||||
| 		if (!access_ok(VERIFY_READ, vaddr, 4)) { | ||||
| 		if (!access_ok(VERIFY_READ, (void __user *)vaddr, 4)) { | ||||
| 			current->thread.cp0_baduaddr = vaddr; | ||||
| 			err = SIGBUS; | ||||
| 			break; | ||||
|  | @ -2021,7 +2021,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) | |||
| 			err = SIGBUS; | ||||
| 			break; | ||||
| 		} | ||||
| 		if (!access_ok(VERIFY_WRITE, vaddr, 4)) { | ||||
| 		if (!access_ok(VERIFY_WRITE, (void __user *)vaddr, 4)) { | ||||
| 			current->thread.cp0_baduaddr = vaddr; | ||||
| 			err = SIGBUS; | ||||
| 			break; | ||||
|  | @ -2084,7 +2084,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) | |||
| 			err = SIGBUS; | ||||
| 			break; | ||||
| 		} | ||||
| 		if (!access_ok(VERIFY_READ, vaddr, 8)) { | ||||
| 		if (!access_ok(VERIFY_READ, (void __user *)vaddr, 8)) { | ||||
| 			current->thread.cp0_baduaddr = vaddr; | ||||
| 			err = SIGBUS; | ||||
| 			break; | ||||
|  | @ -2145,7 +2145,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) | |||
| 			err = SIGBUS; | ||||
| 			break; | ||||
| 		} | ||||
| 		if (!access_ok(VERIFY_WRITE, vaddr, 8)) { | ||||
| 		if (!access_ok(VERIFY_WRITE, (void __user *)vaddr, 8)) { | ||||
| 			current->thread.cp0_baduaddr = vaddr; | ||||
| 			err = SIGBUS; | ||||
| 			break; | ||||
|  |  | |||
|  | @ -98,7 +98,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new) | |||
| 	if (unlikely(addr & 3)) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	if (unlikely(!access_ok(VERIFY_WRITE, addr, 4))) | ||||
| 	if (unlikely(!access_ok(VERIFY_WRITE, (const void __user *)addr, 4))) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	if (cpu_has_llsc && R10000_LLSC_WAR) { | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ struct stackframe { | |||
| static inline int get_mem(unsigned long addr, unsigned long *result) | ||||
| { | ||||
| 	unsigned long *address = (unsigned long *) addr; | ||||
| 	if (!access_ok(VERIFY_READ, addr, sizeof(unsigned long))) | ||||
| 	if (!access_ok(VERIFY_READ, address, sizeof(unsigned long))) | ||||
| 		return -1; | ||||
| 	if (__copy_from_user_inatomic(result, address, sizeof(unsigned long))) | ||||
| 		return -3; | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Al Viro
						Al Viro