Commit f0a955f4 authored by Al Viro's avatar Al Viro

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 054838bc
...@@ -128,23 +128,14 @@ static inline bool eva_kernel_access(void) ...@@ -128,23 +128,14 @@ static inline bool eva_kernel_access(void)
* this function, memory access functions may still return -EFAULT. * this function, memory access functions may still return -EFAULT.
*/ */
#define __access_mask get_fs().seg static inline int __access_ok(const void __user *p, unsigned long size)
{
#define __access_ok(addr, size, mask) \ unsigned long addr = (unsigned long)p;
({ \ return (get_fs().seg & (addr | (addr + size) | __ua_size(size))) == 0;
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; \
})
#define access_ok(type, addr, size) \ #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. * 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) ...@@ -1200,7 +1200,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31)
case lwl_op: case lwl_op:
rt = regs->regs[MIPSInst_RT(inst)]; rt = regs->regs[MIPSInst_RT(inst)];
vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(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; current->thread.cp0_baduaddr = vaddr;
err = SIGSEGV; err = SIGSEGV;
break; break;
...@@ -1273,7 +1273,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) ...@@ -1273,7 +1273,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31)
case lwr_op: case lwr_op:
rt = regs->regs[MIPSInst_RT(inst)]; rt = regs->regs[MIPSInst_RT(inst)];
vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(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; current->thread.cp0_baduaddr = vaddr;
err = SIGSEGV; err = SIGSEGV;
break; break;
...@@ -1347,7 +1347,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) ...@@ -1347,7 +1347,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31)
case swl_op: case swl_op:
rt = regs->regs[MIPSInst_RT(inst)]; rt = regs->regs[MIPSInst_RT(inst)];
vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(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; current->thread.cp0_baduaddr = vaddr;
err = SIGSEGV; err = SIGSEGV;
break; break;
...@@ -1417,7 +1417,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) ...@@ -1417,7 +1417,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31)
case swr_op: case swr_op:
rt = regs->regs[MIPSInst_RT(inst)]; rt = regs->regs[MIPSInst_RT(inst)];
vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(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; current->thread.cp0_baduaddr = vaddr;
err = SIGSEGV; err = SIGSEGV;
break; break;
...@@ -1492,7 +1492,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) ...@@ -1492,7 +1492,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31)
rt = regs->regs[MIPSInst_RT(inst)]; rt = regs->regs[MIPSInst_RT(inst)];
vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(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; current->thread.cp0_baduaddr = vaddr;
err = SIGSEGV; err = SIGSEGV;
break; break;
...@@ -1611,7 +1611,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) ...@@ -1611,7 +1611,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31)
rt = regs->regs[MIPSInst_RT(inst)]; rt = regs->regs[MIPSInst_RT(inst)];
vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(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; current->thread.cp0_baduaddr = vaddr;
err = SIGSEGV; err = SIGSEGV;
break; break;
...@@ -1730,7 +1730,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) ...@@ -1730,7 +1730,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31)
rt = regs->regs[MIPSInst_RT(inst)]; rt = regs->regs[MIPSInst_RT(inst)];
vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(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; current->thread.cp0_baduaddr = vaddr;
err = SIGSEGV; err = SIGSEGV;
break; break;
...@@ -1848,7 +1848,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) ...@@ -1848,7 +1848,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31)
rt = regs->regs[MIPSInst_RT(inst)]; rt = regs->regs[MIPSInst_RT(inst)];
vaddr = regs->regs[MIPSInst_RS(inst)] + MIPSInst_SIMM(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; current->thread.cp0_baduaddr = vaddr;
err = SIGSEGV; err = SIGSEGV;
break; break;
...@@ -1965,7 +1965,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) ...@@ -1965,7 +1965,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31)
err = SIGBUS; err = SIGBUS;
break; break;
} }
if (!access_ok(VERIFY_READ, vaddr, 4)) { if (!access_ok(VERIFY_READ, (void __user *)vaddr, 4)) {
current->thread.cp0_baduaddr = vaddr; current->thread.cp0_baduaddr = vaddr;
err = SIGBUS; err = SIGBUS;
break; break;
...@@ -2021,7 +2021,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) ...@@ -2021,7 +2021,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31)
err = SIGBUS; err = SIGBUS;
break; break;
} }
if (!access_ok(VERIFY_WRITE, vaddr, 4)) { if (!access_ok(VERIFY_WRITE, (void __user *)vaddr, 4)) {
current->thread.cp0_baduaddr = vaddr; current->thread.cp0_baduaddr = vaddr;
err = SIGBUS; err = SIGBUS;
break; break;
...@@ -2084,7 +2084,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) ...@@ -2084,7 +2084,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31)
err = SIGBUS; err = SIGBUS;
break; break;
} }
if (!access_ok(VERIFY_READ, vaddr, 8)) { if (!access_ok(VERIFY_READ, (void __user *)vaddr, 8)) {
current->thread.cp0_baduaddr = vaddr; current->thread.cp0_baduaddr = vaddr;
err = SIGBUS; err = SIGBUS;
break; break;
...@@ -2145,7 +2145,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) ...@@ -2145,7 +2145,7 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31)
err = SIGBUS; err = SIGBUS;
break; break;
} }
if (!access_ok(VERIFY_WRITE, vaddr, 8)) { if (!access_ok(VERIFY_WRITE, (void __user *)vaddr, 8)) {
current->thread.cp0_baduaddr = vaddr; current->thread.cp0_baduaddr = vaddr;
err = SIGBUS; err = SIGBUS;
break; break;
......
...@@ -98,7 +98,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new) ...@@ -98,7 +98,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new)
if (unlikely(addr & 3)) if (unlikely(addr & 3))
return -EINVAL; return -EINVAL;
if (unlikely(!access_ok(VERIFY_WRITE, addr, 4))) if (unlikely(!access_ok(VERIFY_WRITE, (const void __user *)addr, 4)))
return -EINVAL; return -EINVAL;
if (cpu_has_llsc && R10000_LLSC_WAR) { if (cpu_has_llsc && R10000_LLSC_WAR) {
......
...@@ -18,7 +18,7 @@ struct stackframe { ...@@ -18,7 +18,7 @@ struct stackframe {
static inline int get_mem(unsigned long addr, unsigned long *result) static inline int get_mem(unsigned long addr, unsigned long *result)
{ {
unsigned long *address = (unsigned long *) addr; 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; return -1;
if (__copy_from_user_inatomic(result, address, sizeof(unsigned long))) if (__copy_from_user_inatomic(result, address, sizeof(unsigned long)))
return -3; return -3;
......
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