Commit def0bfdb authored by Christophe Leroy's avatar Christophe Leroy Committed by Michael Ellerman

powerpc: use probe_user_read() and probe_user_write()

Instead of opencoding, use probe_user_read() to failessly read
a user location and probe_user_write() for writing to user.
Signed-off-by: default avatarChristophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/e041f5eedb23f09ab553be8a91c3de2087147320.1579800517.git.christophe.leroy@c-s.fr
parent 1e353198
...@@ -1277,16 +1277,6 @@ void show_user_instructions(struct pt_regs *regs) ...@@ -1277,16 +1277,6 @@ void show_user_instructions(struct pt_regs *regs)
pc = regs->nip - (NR_INSN_TO_PRINT * 3 / 4 * sizeof(int)); pc = regs->nip - (NR_INSN_TO_PRINT * 3 / 4 * sizeof(int));
/*
* Make sure the NIP points at userspace, not kernel text/data or
* elsewhere.
*/
if (!__access_ok(pc, NR_INSN_TO_PRINT * sizeof(int), USER_DS)) {
pr_info("%s[%d]: Bad NIP, not dumping instructions.\n",
current->comm, current->pid);
return;
}
seq_buf_init(&s, buf, sizeof(buf)); seq_buf_init(&s, buf, sizeof(buf));
while (n) { while (n) {
...@@ -1297,7 +1287,7 @@ void show_user_instructions(struct pt_regs *regs) ...@@ -1297,7 +1287,7 @@ void show_user_instructions(struct pt_regs *regs)
for (i = 0; i < 8 && n; i++, n--, pc += sizeof(int)) { for (i = 0; i < 8 && n; i++, n--, pc += sizeof(int)) {
int instr; int instr;
if (probe_kernel_address((const void *)pc, instr)) { if (probe_user_read(&instr, (void __user *)pc, sizeof(instr))) {
seq_buf_printf(&s, "XXXXXXXX "); seq_buf_printf(&s, "XXXXXXXX ");
continue; continue;
} }
......
...@@ -63,12 +63,10 @@ unsigned long __kvmhv_copy_tofrom_guest_radix(int lpid, int pid, ...@@ -63,12 +63,10 @@ unsigned long __kvmhv_copy_tofrom_guest_radix(int lpid, int pid,
} }
isync(); isync();
pagefault_disable();
if (is_load) if (is_load)
ret = raw_copy_from_user(to, from, n); ret = probe_user_read(to, (const void __user *)from, n);
else else
ret = raw_copy_to_user(to, from, n); ret = probe_user_write((void __user *)to, from, n);
pagefault_enable();
/* switch the pid first to avoid running host with unallocated pid */ /* switch the pid first to avoid running host with unallocated pid */
if (quadrant == 1 && pid != old_pid) if (quadrant == 1 && pid != old_pid)
......
...@@ -279,12 +279,8 @@ static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address, ...@@ -279,12 +279,8 @@ static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address,
if ((flags & FAULT_FLAG_WRITE) && (flags & FAULT_FLAG_USER) && if ((flags & FAULT_FLAG_WRITE) && (flags & FAULT_FLAG_USER) &&
access_ok(nip, sizeof(*nip))) { access_ok(nip, sizeof(*nip))) {
unsigned int inst; unsigned int inst;
int res;
pagefault_disable(); if (!probe_user_read(&inst, nip, sizeof(inst)))
res = __get_user_inatomic(inst, nip);
pagefault_enable();
if (!res)
return !store_updates_sp(inst); return !store_updates_sp(inst);
*must_retry = true; *must_retry = true;
} }
......
...@@ -28,15 +28,12 @@ static unsigned int user_getsp32(unsigned int sp, int is_first) ...@@ -28,15 +28,12 @@ static unsigned int user_getsp32(unsigned int sp, int is_first)
unsigned int stack_frame[2]; unsigned int stack_frame[2];
void __user *p = compat_ptr(sp); void __user *p = compat_ptr(sp);
if (!access_ok(p, sizeof(stack_frame)))
return 0;
/* /*
* The most likely reason for this is that we returned -EFAULT, * The most likely reason for this is that we returned -EFAULT,
* which means that we've done all that we can do from * which means that we've done all that we can do from
* interrupt context. * interrupt context.
*/ */
if (__copy_from_user_inatomic(stack_frame, p, sizeof(stack_frame))) if (probe_user_read(stack_frame, (void __user *)p, sizeof(stack_frame)))
return 0; return 0;
if (!is_first) if (!is_first)
...@@ -54,11 +51,7 @@ static unsigned long user_getsp64(unsigned long sp, int is_first) ...@@ -54,11 +51,7 @@ static unsigned long user_getsp64(unsigned long sp, int is_first)
{ {
unsigned long stack_frame[3]; unsigned long stack_frame[3];
if (!access_ok((void __user *)sp, sizeof(stack_frame))) if (probe_user_read(stack_frame, (void __user *)sp, sizeof(stack_frame)))
return 0;
if (__copy_from_user_inatomic(stack_frame, (void __user *)sp,
sizeof(stack_frame)))
return 0; return 0;
if (!is_first) if (!is_first)
...@@ -103,7 +96,6 @@ void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth) ...@@ -103,7 +96,6 @@ void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth)
first_frame = 0; first_frame = 0;
} }
} else { } else {
pagefault_disable();
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
if (!is_32bit_task()) { if (!is_32bit_task()) {
while (depth--) { while (depth--) {
...@@ -112,7 +104,6 @@ void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth) ...@@ -112,7 +104,6 @@ void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth)
break; break;
first_frame = 0; first_frame = 0;
} }
pagefault_enable();
return; return;
} }
#endif #endif
...@@ -123,6 +114,5 @@ void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth) ...@@ -123,6 +114,5 @@ void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth)
break; break;
first_frame = 0; first_frame = 0;
} }
pagefault_enable();
} }
} }
...@@ -155,12 +155,8 @@ static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret) ...@@ -155,12 +155,8 @@ static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret)
((unsigned long)ptr & 7)) ((unsigned long)ptr & 7))
return -EFAULT; return -EFAULT;
pagefault_disable(); if (!probe_user_read(ret, ptr, sizeof(*ret)))
if (!__get_user_inatomic(*ret, ptr)) {
pagefault_enable();
return 0; return 0;
}
pagefault_enable();
return read_user_stack_slow(ptr, ret, 8); return read_user_stack_slow(ptr, ret, 8);
} }
...@@ -171,12 +167,8 @@ static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) ...@@ -171,12 +167,8 @@ static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret)
((unsigned long)ptr & 3)) ((unsigned long)ptr & 3))
return -EFAULT; return -EFAULT;
pagefault_disable(); if (!probe_user_read(ret, ptr, sizeof(*ret)))
if (!__get_user_inatomic(*ret, ptr)) {
pagefault_enable();
return 0; return 0;
}
pagefault_enable();
return read_user_stack_slow(ptr, ret, 4); return read_user_stack_slow(ptr, ret, 4);
} }
...@@ -293,17 +285,11 @@ static void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry, ...@@ -293,17 +285,11 @@ static void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry,
*/ */
static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret)
{ {
int rc;
if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) || if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) ||
((unsigned long)ptr & 3)) ((unsigned long)ptr & 3))
return -EFAULT; return -EFAULT;
pagefault_disable(); return probe_user_read(ret, ptr, sizeof(*ret));
rc = __get_user_inatomic(*ret, ptr);
pagefault_enable();
return rc;
} }
static inline void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry, static inline void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry,
......
...@@ -415,7 +415,6 @@ static void power_pmu_sched_task(struct perf_event_context *ctx, bool sched_in) ...@@ -415,7 +415,6 @@ static void power_pmu_sched_task(struct perf_event_context *ctx, bool sched_in)
static __u64 power_pmu_bhrb_to(u64 addr) static __u64 power_pmu_bhrb_to(u64 addr)
{ {
unsigned int instr; unsigned int instr;
int ret;
__u64 target; __u64 target;
if (is_kernel_addr(addr)) { if (is_kernel_addr(addr)) {
...@@ -426,13 +425,8 @@ static __u64 power_pmu_bhrb_to(u64 addr) ...@@ -426,13 +425,8 @@ static __u64 power_pmu_bhrb_to(u64 addr)
} }
/* Userspace: need copy instruction here then translate it */ /* Userspace: need copy instruction here then translate it */
pagefault_disable(); if (probe_user_read(&instr, (unsigned int __user *)addr, sizeof(instr)))
ret = __get_user_inatomic(instr, (unsigned int __user *)addr);
if (ret) {
pagefault_enable();
return 0; return 0;
}
pagefault_enable();
target = branch_target(&instr); target = branch_target(&instr);
if ((!target) || (instr & BRANCH_ABSOLUTE)) if ((!target) || (instr & BRANCH_ABSOLUTE))
......
...@@ -1065,13 +1065,11 @@ int fsl_pci_mcheck_exception(struct pt_regs *regs) ...@@ -1065,13 +1065,11 @@ int fsl_pci_mcheck_exception(struct pt_regs *regs)
addr += mfspr(SPRN_MCAR); addr += mfspr(SPRN_MCAR);
if (is_in_pci_mem_space(addr)) { if (is_in_pci_mem_space(addr)) {
if (user_mode(regs)) { if (user_mode(regs))
pagefault_disable(); ret = probe_user_read(&inst, (void __user *)regs->nip,
ret = get_user(inst, (__u32 __user *)regs->nip); sizeof(inst));
pagefault_enable(); else
} else {
ret = probe_kernel_address((void *)regs->nip, inst); ret = probe_kernel_address((void *)regs->nip, inst);
}
if (!ret && mcheck_handle_load(regs, inst)) { if (!ret && mcheck_handle_load(regs, inst)) {
regs->nip += 4; regs->nip += 4;
......
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