Skip to content

Commit

Permalink
Merge branch 'hch' (maccess patches from Christoph Hellwig)
Browse files Browse the repository at this point in the history
Merge non-faulting memory access cleanups from Christoph Hellwig:
 "Andrew and I decided to drop the patches implementing your suggested
  rename of the probe_kernel_* and probe_user_* helpers from -mm as
  there were way to many conflicts.

  After -rc1 might be a good time for this as all the conflicts are
  resolved now"

This also adds a type safety checking patch on top of the renaming
series to make the subtle behavioral difference between 'get_user()' and
'get_kernel_nofault()' less potentially dangerous and surprising.

* emailed patches from Christoph Hellwig <[email protected]>:
  maccess: make get_kernel_nofault() check for minimal type compatibility
  maccess: rename probe_kernel_address to get_kernel_nofault
  maccess: rename probe_user_{read,write} to copy_{from,to}_user_nofault
  maccess: rename probe_kernel_{read,write} to copy_{from,to}_kernel_nofault
  • Loading branch information
torvalds committed Jun 18, 2020
2 parents 670d0a4 + 0c389d8 commit 5e857ce
Show file tree
Hide file tree
Showing 70 changed files with 207 additions and 185 deletions.
3 changes: 2 additions & 1 deletion arch/arm/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ static int ftrace_modify_code(unsigned long pc, unsigned long old,
old = __opcode_to_mem_arm(old);

if (validate) {
if (probe_kernel_read(&replaced, (void *)pc, MCOUNT_INSN_SIZE))
if (copy_from_kernel_nofault(&replaced, (void *)pc,
MCOUNT_INSN_SIZE))
return -EFAULT;

if (replaced != old)
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/kernel/kgdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
/* patch_text() only supports int-sized breakpoints */
BUILD_BUG_ON(sizeof(int) != BREAK_INSTR_SIZE);

err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
err = copy_from_kernel_nofault(bpt->saved_instr, (char *)bpt->bpt_addr,
BREAK_INSTR_SIZE);
if (err)
return err;
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ int is_valid_bugaddr(unsigned long pc)
u32 insn = __opcode_to_mem_arm(BUG_INSTR_VALUE);
#endif

if (probe_kernel_address((unsigned *)pc, bkpt))
if (get_kernel_nofault(bkpt, (void *)pc))
return 0;

return bkpt == insn;
Expand Down
4 changes: 2 additions & 2 deletions arch/arm/mm/alignment.c
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,7 @@ static int alignment_get_arm(struct pt_regs *regs, u32 *ip, u32 *inst)
if (user_mode(regs))
fault = get_user(instr, ip);
else
fault = probe_kernel_address(ip, instr);
fault = get_kernel_nofault(instr, ip);

*inst = __mem_to_opcode_arm(instr);

Expand All @@ -789,7 +789,7 @@ static int alignment_get_thumb(struct pt_regs *regs, u16 *ip, u16 *inst)
if (user_mode(regs))
fault = get_user(instr, ip);
else
fault = probe_kernel_address(ip, instr);
fault = get_kernel_nofault(instr, ip);

*inst = __mem_to_opcode_thumb16(instr);

Expand Down
4 changes: 2 additions & 2 deletions arch/arm64/kernel/insn.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ int __kprobes aarch64_insn_read(void *addr, u32 *insnp)
int ret;
__le32 val;

ret = probe_kernel_read(&val, addr, AARCH64_INSN_SIZE);
ret = copy_from_kernel_nofault(&val, addr, AARCH64_INSN_SIZE);
if (!ret)
*insnp = le32_to_cpu(val);

Expand All @@ -151,7 +151,7 @@ static int __kprobes __aarch64_insn_write(void *addr, __le32 insn)
raw_spin_lock_irqsave(&patch_lock, flags);
waddr = patch_map(addr, FIX_TEXT_POKE0);

ret = probe_kernel_write(waddr, &insn, AARCH64_INSN_SIZE);
ret = copy_to_kernel_nofault(waddr, &insn, AARCH64_INSN_SIZE);

patch_unmap(FIX_TEXT_POKE0);
raw_spin_unlock_irqrestore(&patch_lock, flags);
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ static int call_undef_hook(struct pt_regs *regs)

if (!user_mode(regs)) {
__le32 instr_le;
if (probe_kernel_address((__force __le32 *)pc, instr_le))
if (get_kernel_nofault(instr_le, (__force __le32 *)pc))
goto exit;
instr = le32_to_cpu(instr_le);
} else if (compat_thumb_mode(regs)) {
Expand Down
5 changes: 3 additions & 2 deletions arch/csky/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ static int ftrace_check_current_nop(unsigned long hook)
uint16_t olds[7];
unsigned long hook_pos = hook - 2;

if (probe_kernel_read((void *)olds, (void *)hook_pos, sizeof(nops)))
if (copy_from_kernel_nofault((void *)olds, (void *)hook_pos,
sizeof(nops)))
return -EFAULT;

if (memcmp((void *)nops, (void *)olds, sizeof(nops))) {
Expand All @@ -97,7 +98,7 @@ static int ftrace_modify_code(unsigned long hook, unsigned long target,

make_jbsr(target, hook, call, nolr);

ret = probe_kernel_write((void *)hook_pos, enable ? call : nops,
ret = copy_to_kernel_nofault((void *)hook_pos, enable ? call : nops,
sizeof(nops));
if (ret)
return -EPERM;
Expand Down
2 changes: 1 addition & 1 deletion arch/ia64/include/asm/sections.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ static inline void *dereference_function_descriptor(void *ptr)
struct fdesc *desc = ptr;
void *p;

if (!probe_kernel_address(&desc->ip, p))
if (!get_kernel_nofault(p, (void *)&desc->ip))
ptr = p;
return ptr;
}
Expand Down
6 changes: 3 additions & 3 deletions arch/ia64/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code,
goto skip_check;

/* read the text we want to modify */
if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
if (copy_from_kernel_nofault(replaced, (void *)ip, MCOUNT_INSN_SIZE))
return -EFAULT;

/* Make sure it is what we expect it to be */
Expand All @@ -117,7 +117,7 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code,

skip_check:
/* replace the text with the new text */
if (probe_kernel_write(((void *)ip), new_code, MCOUNT_INSN_SIZE))
if (copy_to_kernel_nofault(((void *)ip), new_code, MCOUNT_INSN_SIZE))
return -EPERM;
flush_icache_range(ip, ip + MCOUNT_INSN_SIZE);

Expand All @@ -129,7 +129,7 @@ static int ftrace_make_nop_check(struct dyn_ftrace *rec, unsigned long addr)
unsigned char __attribute__((aligned(8))) replaced[MCOUNT_INSN_SIZE];
unsigned long ip = rec->ip;

if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
if (copy_from_kernel_nofault(replaced, (void *)ip, MCOUNT_INSN_SIZE))
return -EFAULT;
if (rec->flags & FTRACE_FL_CONVERTED) {
struct ftrace_call_insn *call_insn, *tmp_call;
Expand Down
6 changes: 3 additions & 3 deletions arch/mips/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
goto out;
}

if ((probe_kernel_read(&prev_insn, p->addr - 1,
sizeof(mips_instruction)) == 0) &&
insn_has_delayslot(prev_insn)) {
if (copy_from_kernel_nofault(&prev_insn, p->addr - 1,
sizeof(mips_instruction)) == 0 &&
insn_has_delayslot(prev_insn)) {
pr_notice("Kprobes for branch delayslot are not supported\n");
ret = -EINVAL;
goto out;
Expand Down
5 changes: 3 additions & 2 deletions arch/nds32/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,14 @@ static int __ftrace_modify_code(unsigned long pc, unsigned long *old_insn,
unsigned long orig_insn[3];

if (validate) {
if (probe_kernel_read(orig_insn, (void *)pc, MCOUNT_INSN_SIZE))
if (copy_from_kernel_nofault(orig_insn, (void *)pc,
MCOUNT_INSN_SIZE))
return -EFAULT;
if (memcmp(orig_insn, old_insn, MCOUNT_INSN_SIZE))
return -EINVAL;
}

if (probe_kernel_write((void *)pc, new_insn, MCOUNT_INSN_SIZE))
if (copy_to_kernel_nofault((void *)pc, new_insn, MCOUNT_INSN_SIZE))
return -EPERM;

return 0;
Expand Down
2 changes: 1 addition & 1 deletion arch/parisc/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)

ip = (void *)(rec->ip + 4 - size);

ret = probe_kernel_read(insn, ip, size);
ret = copy_from_kernel_nofault(insn, ip, size);
if (ret)
return ret;

Expand Down
4 changes: 2 additions & 2 deletions arch/parisc/kernel/kgdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)

int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
{
int ret = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
BREAK_INSTR_SIZE);
int ret = copy_from_kernel_nofault(bpt->saved_instr,
(char *)bpt->bpt_addr, BREAK_INSTR_SIZE);
if (ret)
return ret;

Expand Down
2 changes: 1 addition & 1 deletion arch/parisc/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ void *dereference_function_descriptor(void *ptr)
Elf64_Fdesc *desc = ptr;
void *p;

if (!probe_kernel_address(&desc->addr, p))
if (!get_kernel_nofault(p, (void *)&desc->addr))
ptr = p;
return ptr;
}
Expand Down
2 changes: 1 addition & 1 deletion arch/parisc/lib/memcpy.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ void * memcpy(void * dst,const void *src, size_t count)
EXPORT_SYMBOL(raw_copy_in_user);
EXPORT_SYMBOL(memcpy);

bool probe_kernel_read_allowed(const void *unsafe_src, size_t size)
bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
{
if ((unsigned long)unsafe_src < PAGE_SIZE)
return false;
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/include/asm/sections.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ static inline void *dereference_function_descriptor(void *ptr)
struct ppc64_opd_entry *desc = ptr;
void *p;

if (!probe_kernel_address(&desc->funcaddr, p))
if (!get_kernel_nofault(p, (void *)&desc->funcaddr))
ptr = p;
return ptr;
}
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/kgdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
unsigned int instr;
struct ppc_inst *addr = (struct ppc_inst *)bpt->bpt_addr;

err = probe_kernel_address(addr, instr);
err = get_kernel_nofault(instr, (unsigned *) addr);
if (err)
return err;

Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ int kprobe_handler(struct pt_regs *regs)
if (!p) {
unsigned int instr;

if (probe_kernel_address(addr, instr))
if (get_kernel_nofault(instr, addr))
goto no_kprobe;

if (instr != BREAKPOINT_INSTRUCTION) {
Expand Down
6 changes: 4 additions & 2 deletions arch/powerpc/kernel/module_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -756,7 +756,8 @@ int module_trampoline_target(struct module *mod, unsigned long addr,

stub = (struct ppc64_stub_entry *)addr;

if (probe_kernel_read(&magic, &stub->magic, sizeof(magic))) {
if (copy_from_kernel_nofault(&magic, &stub->magic,
sizeof(magic))) {
pr_err("%s: fault reading magic for stub %lx for %s\n", __func__, addr, mod->name);
return -EFAULT;
}
Expand All @@ -766,7 +767,8 @@ int module_trampoline_target(struct module *mod, unsigned long addr,
return -EFAULT;
}

if (probe_kernel_read(&funcdata, &stub->funcdata, sizeof(funcdata))) {
if (copy_from_kernel_nofault(&funcdata, &stub->funcdata,
sizeof(funcdata))) {
pr_err("%s: fault reading funcdata for stub %lx for %s\n", __func__, addr, mod->name);
return -EFAULT;
}
Expand Down
5 changes: 3 additions & 2 deletions arch/powerpc/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -1271,7 +1271,7 @@ static void show_instructions(struct pt_regs *regs)
#endif

if (!__kernel_text_address(pc) ||
probe_kernel_address((const void *)pc, instr)) {
get_kernel_nofault(instr, (const void *)pc)) {
pr_cont("XXXXXXXX ");
} else {
if (regs->nip == pc)
Expand Down Expand Up @@ -1305,7 +1305,8 @@ void show_user_instructions(struct pt_regs *regs)
for (i = 0; i < 8 && n; i++, n--, pc += sizeof(int)) {
int instr;

if (probe_user_read(&instr, (void __user *)pc, sizeof(instr))) {
if (copy_from_user_nofault(&instr, (void __user *)pc,
sizeof(instr))) {
seq_buf_printf(&s, "XXXXXXXX ");
continue;
}
Expand Down
4 changes: 2 additions & 2 deletions arch/powerpc/kernel/trace/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ __ftrace_make_nop(struct module *mod,
unsigned long ip = rec->ip;
unsigned long tramp;

if (probe_kernel_read(&op, (void *)ip, MCOUNT_INSN_SIZE))
if (copy_from_kernel_nofault(&op, (void *)ip, MCOUNT_INSN_SIZE))
return -EFAULT;

/* Make sure that that this is still a 24bit jump */
Expand All @@ -249,7 +249,7 @@ __ftrace_make_nop(struct module *mod,
pr_devel("ip:%lx jumps to %lx", ip, tramp);

/* Find where the trampoline jumps to */
if (probe_kernel_read(jmp, (void *)tramp, sizeof(jmp))) {
if (copy_from_kernel_nofault(jmp, (void *)tramp, sizeof(jmp))) {
pr_err("Failed to read %lx\n", tramp);
return -EFAULT;
}
Expand Down
4 changes: 2 additions & 2 deletions arch/powerpc/kvm/book3s_64_mmu_radix.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ unsigned long __kvmhv_copy_tofrom_guest_radix(int lpid, int pid,
isync();

if (is_load)
ret = probe_user_read(to, (const void __user *)from, n);
ret = copy_from_user_nofault(to, (const void __user *)from, n);
else
ret = probe_user_write((void __user *)to, from, n);
ret = copy_to_user_nofault((void __user *)to, from, n);

/* switch the pid first to avoid running host with unallocated pid */
if (quadrant == 1 && pid != old_pid)
Expand Down
12 changes: 6 additions & 6 deletions arch/powerpc/lib/inst.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ int probe_user_read_inst(struct ppc_inst *inst,
unsigned int val, suffix;
int err;

err = probe_user_read(&val, nip, sizeof(val));
err = copy_from_user_nofault(&val, nip, sizeof(val));
if (err)
return err;
if (get_op(val) == OP_PREFIX) {
err = probe_user_read(&suffix, (void __user *)nip + 4, 4);
err = copy_from_user_nofault(&suffix, (void __user *)nip + 4, 4);
*inst = ppc_inst_prefix(val, suffix);
} else {
*inst = ppc_inst(val);
Expand All @@ -33,11 +33,11 @@ int probe_kernel_read_inst(struct ppc_inst *inst,
unsigned int val, suffix;
int err;

err = probe_kernel_read(&val, src, sizeof(val));
err = copy_from_kernel_nofault(&val, src, sizeof(val));
if (err)
return err;
if (get_op(val) == OP_PREFIX) {
err = probe_kernel_read(&suffix, (void *)src + 4, 4);
err = copy_from_kernel_nofault(&suffix, (void *)src + 4, 4);
*inst = ppc_inst_prefix(val, suffix);
} else {
*inst = ppc_inst(val);
Expand All @@ -51,7 +51,7 @@ int probe_user_read_inst(struct ppc_inst *inst,
unsigned int val;
int err;

err = probe_user_read(&val, nip, sizeof(val));
err = copy_from_user_nofault(&val, nip, sizeof(val));
if (!err)
*inst = ppc_inst(val);

Expand All @@ -64,7 +64,7 @@ int probe_kernel_read_inst(struct ppc_inst *inst,
unsigned int val;
int err;

err = probe_kernel_read(&val, src, sizeof(val));
err = copy_from_kernel_nofault(&val, src, sizeof(val));
if (!err)
*inst = ppc_inst(val);

Expand Down
6 changes: 4 additions & 2 deletions arch/powerpc/oprofile/backtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ static unsigned int user_getsp32(unsigned int sp, int is_first)
* which means that we've done all that we can do from
* interrupt context.
*/
if (probe_user_read(stack_frame, (void __user *)p, sizeof(stack_frame)))
if (copy_from_user_nofault(stack_frame, (void __user *)p,
sizeof(stack_frame)))
return 0;

if (!is_first)
Expand All @@ -51,7 +52,8 @@ static unsigned long user_getsp64(unsigned long sp, int is_first)
{
unsigned long stack_frame[3];

if (probe_user_read(stack_frame, (void __user *)sp, sizeof(stack_frame)))
if (copy_from_user_nofault(stack_frame, (void __user *)sp,
sizeof(stack_frame)))
return 0;

if (!is_first)
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/perf/callchain_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret)
((unsigned long)ptr & 3))
return -EFAULT;

rc = probe_user_read(ret, ptr, sizeof(*ret));
rc = copy_from_user_nofault(ret, ptr, sizeof(*ret));

if (IS_ENABLED(CONFIG_PPC64) && rc)
return read_user_stack_slow(ptr, ret, 4);
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/perf/callchain_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret)
((unsigned long)ptr & 7))
return -EFAULT;

if (!probe_user_read(ret, ptr, sizeof(*ret)))
if (!copy_from_user_nofault(ret, ptr, sizeof(*ret)))
return 0;

return read_user_stack_slow(ptr, ret, 8);
Expand Down
6 changes: 4 additions & 2 deletions arch/powerpc/perf/core-book3s.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,14 +418,16 @@ static __u64 power_pmu_bhrb_to(u64 addr)
__u64 target;

if (is_kernel_addr(addr)) {
if (probe_kernel_read(&instr, (void *)addr, sizeof(instr)))
if (copy_from_kernel_nofault(&instr, (void *)addr,
sizeof(instr)))
return 0;

return branch_target((struct ppc_inst *)&instr);
}

/* Userspace: need copy instruction here then translate it */
if (probe_user_read(&instr, (unsigned int __user *)addr, sizeof(instr)))
if (copy_from_user_nofault(&instr, (unsigned int __user *)addr,
sizeof(instr)))
return 0;

target = branch_target((struct ppc_inst *)&instr);
Expand Down
Loading

0 comments on commit 5e857ce

Please sign in to comment.