Merge branch 'hch' (maccess patches from Christoph Hellwig)
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 <hch@lst.de>: 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
This commit is contained in:
Коммит
5e857ce6ea
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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))) {
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1066,10 +1066,10 @@ int fsl_pci_mcheck_exception(struct pt_regs *regs)
|
|||
|
||||
if (is_in_pci_mem_space(addr)) {
|
||||
if (user_mode(regs))
|
||||
ret = probe_user_read(&inst, (void __user *)regs->nip,
|
||||
sizeof(inst));
|
||||
ret = copy_from_user_nofault(&inst,
|
||||
(void __user *)regs->nip, sizeof(inst));
|
||||
else
|
||||
ret = probe_kernel_address((void *)regs->nip, inst);
|
||||
ret = get_kernel_nofault(inst, (void *)regs->nip);
|
||||
|
||||
if (!ret && mcheck_handle_load(regs, inst)) {
|
||||
regs->nip += 4;
|
||||
|
|
|
@ -38,7 +38,8 @@ static int ftrace_check_current_call(unsigned long hook_pos,
|
|||
* Read the text we want to modify;
|
||||
* return must be -EFAULT on read error
|
||||
*/
|
||||
if (probe_kernel_read(replaced, (void *)hook_pos, MCOUNT_INSN_SIZE))
|
||||
if (copy_from_kernel_nofault(replaced, (void *)hook_pos,
|
||||
MCOUNT_INSN_SIZE))
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
|
|
|
@ -62,7 +62,7 @@ int get_step_address(struct pt_regs *regs, unsigned long *next_addr)
|
|||
unsigned int rs1_num, rs2_num;
|
||||
int op_code;
|
||||
|
||||
if (probe_kernel_address((void *)pc, op_code))
|
||||
if (get_kernel_nofault(op_code, (void *)pc))
|
||||
return -EINVAL;
|
||||
if ((op_code & __INSN_LENGTH_MASK) != __INSN_LENGTH_GE_32) {
|
||||
if (is_c_jalr_insn(op_code) || is_c_jr_insn(op_code)) {
|
||||
|
@ -146,14 +146,14 @@ int do_single_step(struct pt_regs *regs)
|
|||
return error;
|
||||
|
||||
/* Store the op code in the stepped address */
|
||||
error = probe_kernel_address((void *)addr, stepped_opcode);
|
||||
error = get_kernel_nofault(stepped_opcode, (void *)addr);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
stepped_address = addr;
|
||||
|
||||
/* Replace the op code with the break instruction */
|
||||
error = probe_kernel_write((void *)stepped_address,
|
||||
error = copy_to_kernel_nofault((void *)stepped_address,
|
||||
arch_kgdb_ops.gdb_bpt_instr,
|
||||
BREAK_INSTR_SIZE);
|
||||
/* Flush and return */
|
||||
|
@ -173,7 +173,7 @@ int do_single_step(struct pt_regs *regs)
|
|||
static void undo_single_step(struct pt_regs *regs)
|
||||
{
|
||||
if (stepped_opcode != 0) {
|
||||
probe_kernel_write((void *)stepped_address,
|
||||
copy_to_kernel_nofault((void *)stepped_address,
|
||||
(void *)&stepped_opcode, BREAK_INSTR_SIZE);
|
||||
flush_icache_range(stepped_address,
|
||||
stepped_address + BREAK_INSTR_SIZE);
|
||||
|
|
|
@ -63,7 +63,7 @@ static int patch_insn_write(void *addr, const void *insn, size_t len)
|
|||
|
||||
waddr = patch_map(addr, FIX_TEXT_POKE0);
|
||||
|
||||
ret = probe_kernel_write(waddr, insn, len);
|
||||
ret = copy_to_kernel_nofault(waddr, insn, len);
|
||||
|
||||
patch_unmap(FIX_TEXT_POKE0);
|
||||
|
||||
|
@ -76,7 +76,7 @@ NOKPROBE_SYMBOL(patch_insn_write);
|
|||
#else
|
||||
static int patch_insn_write(void *addr, const void *insn, size_t len)
|
||||
{
|
||||
return probe_kernel_write(addr, insn, len);
|
||||
return copy_to_kernel_nofault(addr, insn, len);
|
||||
}
|
||||
NOKPROBE_SYMBOL(patch_insn_write);
|
||||
#endif /* CONFIG_MMU */
|
||||
|
|
|
@ -137,7 +137,7 @@ static inline unsigned long get_break_insn_length(unsigned long pc)
|
|||
{
|
||||
bug_insn_t insn;
|
||||
|
||||
if (probe_kernel_address((bug_insn_t *)pc, insn))
|
||||
if (get_kernel_nofault(insn, (bug_insn_t *)pc))
|
||||
return 0;
|
||||
|
||||
return GET_INSN_LENGTH(insn);
|
||||
|
@ -165,7 +165,7 @@ int is_valid_bugaddr(unsigned long pc)
|
|||
|
||||
if (pc < VMALLOC_START)
|
||||
return 0;
|
||||
if (probe_kernel_address((bug_insn_t *)pc, insn))
|
||||
if (get_kernel_nofault(insn, (bug_insn_t *)pc))
|
||||
return 0;
|
||||
if ((insn & __INSN_LENGTH_MASK) == __INSN_LENGTH_32)
|
||||
return (insn == __BUG_INSN_32);
|
||||
|
|
|
@ -83,7 +83,7 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
|
|||
{
|
||||
struct ftrace_insn orig, new, old;
|
||||
|
||||
if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old)))
|
||||
if (copy_from_kernel_nofault(&old, (void *) rec->ip, sizeof(old)))
|
||||
return -EFAULT;
|
||||
if (addr == MCOUNT_ADDR) {
|
||||
/* Initial code replacement */
|
||||
|
@ -105,7 +105,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
|
|||
{
|
||||
struct ftrace_insn orig, new, old;
|
||||
|
||||
if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old)))
|
||||
if (copy_from_kernel_nofault(&old, (void *) rec->ip, sizeof(old)))
|
||||
return -EFAULT;
|
||||
/* Replace nop with an ftrace call. */
|
||||
ftrace_generate_nop_insn(&orig);
|
||||
|
|
|
@ -105,7 +105,7 @@ static int bad_address(void *p)
|
|||
{
|
||||
unsigned long dummy;
|
||||
|
||||
return probe_kernel_address((unsigned long *)p, dummy);
|
||||
return get_kernel_nofault(dummy, (unsigned long *)p);
|
||||
}
|
||||
|
||||
static void dump_pagetable(unsigned long asce, unsigned long address)
|
||||
|
|
|
@ -119,7 +119,7 @@ static void ftrace_mod_code(void)
|
|||
* But if one were to fail, then they all should, and if one were
|
||||
* to succeed, then they all should.
|
||||
*/
|
||||
mod_code_status = probe_kernel_write(mod_code_ip, mod_code_newcode,
|
||||
mod_code_status = copy_to_kernel_nofault(mod_code_ip, mod_code_newcode,
|
||||
MCOUNT_INSN_SIZE);
|
||||
|
||||
/* if we fail, then kill any new writers */
|
||||
|
@ -203,7 +203,7 @@ static int ftrace_modify_code(unsigned long ip, unsigned char *old_code,
|
|||
*/
|
||||
|
||||
/* 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 */
|
||||
|
@ -268,7 +268,7 @@ static int ftrace_mod(unsigned long ip, unsigned long old_addr,
|
|||
{
|
||||
unsigned char code[MCOUNT_INSN_SIZE];
|
||||
|
||||
if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE))
|
||||
if (copy_from_kernel_nofault(code, (void *)ip, MCOUNT_INSN_SIZE))
|
||||
return -EFAULT;
|
||||
|
||||
if (old_addr != __raw_readl((unsigned long *)code))
|
||||
|
|
|
@ -118,7 +118,7 @@ int is_valid_bugaddr(unsigned long addr)
|
|||
|
||||
if (addr < PAGE_OFFSET)
|
||||
return 0;
|
||||
if (probe_kernel_address((insn_size_t *)addr, opcode))
|
||||
if (get_kernel_nofault(opcode, (insn_size_t *)addr))
|
||||
return 0;
|
||||
if (opcode == TRAPA_BUG_OPCODE)
|
||||
return 1;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <os.h>
|
||||
|
||||
bool probe_kernel_read_allowed(const void *src, size_t size)
|
||||
bool copy_from_kernel_nofault_allowed(const void *src, size_t size)
|
||||
{
|
||||
void *psrc = (void *)rounddown((unsigned long)src, PAGE_SIZE);
|
||||
|
||||
|
|
|
@ -278,7 +278,7 @@ static inline unsigned long *regs_get_kernel_stack_nth_addr(struct pt_regs *regs
|
|||
}
|
||||
|
||||
/* To avoid include hell, we can't include uaccess.h */
|
||||
extern long probe_kernel_read(void *dst, const void *src, size_t size);
|
||||
extern long copy_from_kernel_nofault(void *dst, const void *src, size_t size);
|
||||
|
||||
/**
|
||||
* regs_get_kernel_stack_nth() - get Nth entry of the stack
|
||||
|
@ -298,7 +298,7 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
|
|||
|
||||
addr = regs_get_kernel_stack_nth_addr(regs, n);
|
||||
if (addr) {
|
||||
ret = probe_kernel_read(&val, addr, sizeof(val));
|
||||
ret = copy_from_kernel_nofault(&val, addr, sizeof(val));
|
||||
if (!ret)
|
||||
return val;
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ void show_opcodes(struct pt_regs *regs, const char *loglvl)
|
|||
bad_ip = user_mode(regs) &&
|
||||
__chk_range_not_ok(prologue, OPCODE_BUFSIZE, TASK_SIZE_MAX);
|
||||
|
||||
if (bad_ip || probe_kernel_read(opcodes, (u8 *)prologue,
|
||||
if (bad_ip || copy_from_kernel_nofault(opcodes, (u8 *)prologue,
|
||||
OPCODE_BUFSIZE)) {
|
||||
printk("%sCode: Bad RIP value.\n", loglvl);
|
||||
} else {
|
||||
|
|
|
@ -86,7 +86,7 @@ static int ftrace_verify_code(unsigned long ip, const char *old_code)
|
|||
* sure what we read is what we expected it to be before modifying it.
|
||||
*/
|
||||
/* read the text we want to modify */
|
||||
if (probe_kernel_read(cur_code, (void *)ip, MCOUNT_INSN_SIZE)) {
|
||||
if (copy_from_kernel_nofault(cur_code, (void *)ip, MCOUNT_INSN_SIZE)) {
|
||||
WARN_ON(1);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
@ -355,7 +355,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
|
|||
npages = DIV_ROUND_UP(*tramp_size, PAGE_SIZE);
|
||||
|
||||
/* Copy ftrace_caller onto the trampoline memory */
|
||||
ret = probe_kernel_read(trampoline, (void *)start_offset, size);
|
||||
ret = copy_from_kernel_nofault(trampoline, (void *)start_offset, size);
|
||||
if (WARN_ON(ret < 0))
|
||||
goto fail;
|
||||
|
||||
|
@ -363,13 +363,13 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
|
|||
|
||||
/* The trampoline ends with ret(q) */
|
||||
retq = (unsigned long)ftrace_stub;
|
||||
ret = probe_kernel_read(ip, (void *)retq, RET_SIZE);
|
||||
ret = copy_from_kernel_nofault(ip, (void *)retq, RET_SIZE);
|
||||
if (WARN_ON(ret < 0))
|
||||
goto fail;
|
||||
|
||||
if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) {
|
||||
ip = trampoline + (ftrace_regs_caller_ret - ftrace_regs_caller);
|
||||
ret = probe_kernel_read(ip, (void *)retq, RET_SIZE);
|
||||
ret = copy_from_kernel_nofault(ip, (void *)retq, RET_SIZE);
|
||||
if (WARN_ON(ret < 0))
|
||||
goto fail;
|
||||
}
|
||||
|
@ -506,7 +506,7 @@ static void *addr_from_call(void *ptr)
|
|||
union text_poke_insn call;
|
||||
int ret;
|
||||
|
||||
ret = probe_kernel_read(&call, ptr, CALL_INSN_SIZE);
|
||||
ret = copy_from_kernel_nofault(&call, ptr, CALL_INSN_SIZE);
|
||||
if (WARN_ON_ONCE(ret < 0))
|
||||
return NULL;
|
||||
|
||||
|
|
|
@ -732,11 +732,11 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
|
|||
int err;
|
||||
|
||||
bpt->type = BP_BREAKPOINT;
|
||||
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;
|
||||
err = probe_kernel_write((char *)bpt->bpt_addr,
|
||||
err = copy_to_kernel_nofault((char *)bpt->bpt_addr,
|
||||
arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
|
||||
if (!err)
|
||||
return err;
|
||||
|
@ -768,7 +768,7 @@ int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
|
|||
return 0;
|
||||
|
||||
knl_write:
|
||||
return probe_kernel_write((char *)bpt->bpt_addr,
|
||||
return copy_to_kernel_nofault((char *)bpt->bpt_addr,
|
||||
(char *)bpt->saved_instr, BREAK_INSTR_SIZE);
|
||||
}
|
||||
|
||||
|
|
|
@ -243,7 +243,7 @@ __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr)
|
|||
* Fortunately, we know that the original code is the ideal 5-byte
|
||||
* long NOP.
|
||||
*/
|
||||
if (probe_kernel_read(buf, (void *)addr,
|
||||
if (copy_from_kernel_nofault(buf, (void *)addr,
|
||||
MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
|
||||
return 0UL;
|
||||
|
||||
|
@ -346,7 +346,8 @@ int __copy_instruction(u8 *dest, u8 *src, u8 *real, struct insn *insn)
|
|||
return 0;
|
||||
|
||||
/* This can access kernel text if given address is not recovered */
|
||||
if (probe_kernel_read(dest, (void *)recovered_insn, MAX_INSN_SIZE))
|
||||
if (copy_from_kernel_nofault(dest, (void *)recovered_insn,
|
||||
MAX_INSN_SIZE))
|
||||
return 0;
|
||||
|
||||
kernel_insn_init(insn, dest, MAX_INSN_SIZE);
|
||||
|
|
|
@ -56,7 +56,7 @@ found:
|
|||
* overwritten by jump destination address. In this case, original
|
||||
* bytes must be recovered from op->optinsn.copied_insn buffer.
|
||||
*/
|
||||
if (probe_kernel_read(buf, (void *)addr,
|
||||
if (copy_from_kernel_nofault(buf, (void *)addr,
|
||||
MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
|
||||
return 0UL;
|
||||
|
||||
|
|
|
@ -94,12 +94,12 @@ static bool match_id(struct pci_dev *pdev, unsigned short vendor, unsigned short
|
|||
}
|
||||
|
||||
static bool probe_list(struct pci_dev *pdev, unsigned short vendor,
|
||||
const unsigned char *rom_list)
|
||||
const void *rom_list)
|
||||
{
|
||||
unsigned short device;
|
||||
|
||||
do {
|
||||
if (probe_kernel_address(rom_list, device) != 0)
|
||||
if (get_kernel_nofault(device, rom_list) != 0)
|
||||
device = 0;
|
||||
|
||||
if (device && match_id(pdev, vendor, device))
|
||||
|
@ -119,19 +119,19 @@ static struct resource *find_oprom(struct pci_dev *pdev)
|
|||
for (i = 0; i < ARRAY_SIZE(adapter_rom_resources); i++) {
|
||||
struct resource *res = &adapter_rom_resources[i];
|
||||
unsigned short offset, vendor, device, list, rev;
|
||||
const unsigned char *rom;
|
||||
const void *rom;
|
||||
|
||||
if (res->end == 0)
|
||||
break;
|
||||
|
||||
rom = isa_bus_to_virt(res->start);
|
||||
if (probe_kernel_address(rom + 0x18, offset) != 0)
|
||||
if (get_kernel_nofault(offset, rom + 0x18) != 0)
|
||||
continue;
|
||||
|
||||
if (probe_kernel_address(rom + offset + 0x4, vendor) != 0)
|
||||
if (get_kernel_nofault(vendor, rom + offset + 0x4) != 0)
|
||||
continue;
|
||||
|
||||
if (probe_kernel_address(rom + offset + 0x6, device) != 0)
|
||||
if (get_kernel_nofault(device, rom + offset + 0x6) != 0)
|
||||
continue;
|
||||
|
||||
if (match_id(pdev, vendor, device)) {
|
||||
|
@ -139,8 +139,8 @@ static struct resource *find_oprom(struct pci_dev *pdev)
|
|||
break;
|
||||
}
|
||||
|
||||
if (probe_kernel_address(rom + offset + 0x8, list) == 0 &&
|
||||
probe_kernel_address(rom + offset + 0xc, rev) == 0 &&
|
||||
if (get_kernel_nofault(list, rom + offset + 0x8) == 0 &&
|
||||
get_kernel_nofault(rev, rom + offset + 0xc) == 0 &&
|
||||
rev >= 3 && list &&
|
||||
probe_list(pdev, vendor, rom + offset + list)) {
|
||||
oprom = res;
|
||||
|
@ -183,14 +183,14 @@ static int __init romsignature(const unsigned char *rom)
|
|||
const unsigned short * const ptr = (const unsigned short *)rom;
|
||||
unsigned short sig;
|
||||
|
||||
return probe_kernel_address(ptr, sig) == 0 && sig == ROMSIGNATURE;
|
||||
return get_kernel_nofault(sig, ptr) == 0 && sig == ROMSIGNATURE;
|
||||
}
|
||||
|
||||
static int __init romchecksum(const unsigned char *rom, unsigned long length)
|
||||
{
|
||||
unsigned char sum, c;
|
||||
|
||||
for (sum = 0; length && probe_kernel_address(rom++, c) == 0; length--)
|
||||
for (sum = 0; length && get_kernel_nofault(c, rom++) == 0; length--)
|
||||
sum += c;
|
||||
return !length && !sum;
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ void __init probe_roms(void)
|
|||
|
||||
video_rom_resource.start = start;
|
||||
|
||||
if (probe_kernel_address(rom + 2, c) != 0)
|
||||
if (get_kernel_nofault(c, rom + 2) != 0)
|
||||
continue;
|
||||
|
||||
/* 0 < length <= 0x7f * 512, historically */
|
||||
|
@ -249,7 +249,7 @@ void __init probe_roms(void)
|
|||
if (!romsignature(rom))
|
||||
continue;
|
||||
|
||||
if (probe_kernel_address(rom + 2, c) != 0)
|
||||
if (get_kernel_nofault(c, rom + 2) != 0)
|
||||
continue;
|
||||
|
||||
/* 0 < length <= 0x7f * 512, historically */
|
||||
|
|
|
@ -91,7 +91,7 @@ int is_valid_bugaddr(unsigned long addr)
|
|||
if (addr < TASK_SIZE_MAX)
|
||||
return 0;
|
||||
|
||||
if (probe_kernel_address((unsigned short *)addr, ud))
|
||||
if (get_kernel_nofault(ud, (unsigned short *)addr))
|
||||
return 0;
|
||||
|
||||
return ud == INSN_UD0 || ud == INSN_UD2;
|
||||
|
@ -488,7 +488,8 @@ static enum kernel_gp_hint get_kernel_gp_address(struct pt_regs *regs,
|
|||
u8 insn_buf[MAX_INSN_SIZE];
|
||||
struct insn insn;
|
||||
|
||||
if (probe_kernel_read(insn_buf, (void *)regs->ip, MAX_INSN_SIZE))
|
||||
if (copy_from_kernel_nofault(insn_buf, (void *)regs->ip,
|
||||
MAX_INSN_SIZE))
|
||||
return GP_NO_HINT;
|
||||
|
||||
kernel_insn_init(&insn, insn_buf, MAX_INSN_SIZE);
|
||||
|
|
|
@ -99,7 +99,7 @@ check_prefetch_opcode(struct pt_regs *regs, unsigned char *instr,
|
|||
return !instr_lo || (instr_lo>>1) == 1;
|
||||
case 0x00:
|
||||
/* Prefetch instruction is 0x0F0D or 0x0F18 */
|
||||
if (probe_kernel_address(instr, opcode))
|
||||
if (get_kernel_nofault(opcode, instr))
|
||||
return 0;
|
||||
|
||||
*prefetch = (instr_lo == 0xF) &&
|
||||
|
@ -133,7 +133,7 @@ is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr)
|
|||
while (instr < max_instr) {
|
||||
unsigned char opcode;
|
||||
|
||||
if (probe_kernel_address(instr, opcode))
|
||||
if (get_kernel_nofault(opcode, instr))
|
||||
break;
|
||||
|
||||
instr++;
|
||||
|
@ -301,7 +301,7 @@ static int bad_address(void *p)
|
|||
{
|
||||
unsigned long dummy;
|
||||
|
||||
return probe_kernel_address((unsigned long *)p, dummy);
|
||||
return get_kernel_nofault(dummy, (unsigned long *)p);
|
||||
}
|
||||
|
||||
static void dump_pagetable(unsigned long address)
|
||||
|
@ -442,7 +442,7 @@ static void show_ldttss(const struct desc_ptr *gdt, const char *name, u16 index)
|
|||
return;
|
||||
}
|
||||
|
||||
if (probe_kernel_read(&desc, (void *)(gdt->address + offset),
|
||||
if (copy_from_kernel_nofault(&desc, (void *)(gdt->address + offset),
|
||||
sizeof(struct ldttss_desc))) {
|
||||
pr_alert("%s: 0x%hx -- GDT entry is not readable\n",
|
||||
name, index);
|
||||
|
|
|
@ -737,7 +737,7 @@ static void __init test_wp_bit(void)
|
|||
|
||||
__set_fixmap(FIX_WP_TEST, __pa_symbol(empty_zero_page), PAGE_KERNEL_RO);
|
||||
|
||||
if (probe_kernel_write((char *)fix_to_virt(FIX_WP_TEST), &z, 1)) {
|
||||
if (copy_to_kernel_nofault((char *)fix_to_virt(FIX_WP_TEST), &z, 1)) {
|
||||
clear_fixmap(FIX_WP_TEST);
|
||||
printk(KERN_CONT "Ok.\n");
|
||||
return;
|
||||
|
|
|
@ -9,7 +9,7 @@ static __always_inline u64 canonical_address(u64 vaddr, u8 vaddr_bits)
|
|||
return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
unsigned long vaddr = (unsigned long)unsafe_src;
|
||||
|
||||
|
@ -22,7 +22,7 @@ bool probe_kernel_read_allowed(const void *unsafe_src, size_t size)
|
|||
canonical_address(vaddr, boot_cpu_data.x86_virt_bits) == vaddr;
|
||||
}
|
||||
#else
|
||||
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)
|
||||
{
|
||||
return (unsigned long)unsafe_src >= TASK_SIZE_MAX;
|
||||
}
|
||||
|
|
|
@ -302,7 +302,7 @@ static const struct pci_raw_ops *__init pci_find_bios(void)
|
|||
check <= (union bios32 *) __va(0xffff0);
|
||||
++check) {
|
||||
long sig;
|
||||
if (probe_kernel_address(&check->fields.signature, sig))
|
||||
if (get_kernel_nofault(sig, &check->fields.signature))
|
||||
continue;
|
||||
|
||||
if (check->fields.signature != BIOS32_SIGNATURE)
|
||||
|
|
|
@ -386,7 +386,7 @@ static void set_aliased_prot(void *v, pgprot_t prot)
|
|||
|
||||
preempt_disable();
|
||||
|
||||
probe_kernel_read(&dummy, v, 1);
|
||||
copy_from_kernel_nofault(&dummy, v, 1);
|
||||
|
||||
if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0))
|
||||
BUG();
|
||||
|
|
|
@ -171,7 +171,7 @@ static ssize_t read_mem(struct file *file, char __user *buf,
|
|||
if (!ptr)
|
||||
goto failed;
|
||||
|
||||
probe = probe_kernel_read(bounce, ptr, sz);
|
||||
probe = copy_from_kernel_nofault(bounce, ptr, sz);
|
||||
unxlate_dev_mem_ptr(p, ptr);
|
||||
if (probe)
|
||||
goto failed;
|
||||
|
|
|
@ -135,7 +135,8 @@ int __init dio_find(int deviceid)
|
|||
else
|
||||
va = ioremap(pa, PAGE_SIZE);
|
||||
|
||||
if (probe_kernel_read(&i, (unsigned char *)va + DIO_IDOFF, 1)) {
|
||||
if (copy_from_kernel_nofault(&i,
|
||||
(unsigned char *)va + DIO_IDOFF, 1)) {
|
||||
if (scode >= DIOII_SCBASE)
|
||||
iounmap(va);
|
||||
continue; /* no board present at that select code */
|
||||
|
@ -208,7 +209,8 @@ static int __init dio_init(void)
|
|||
else
|
||||
va = ioremap(pa, PAGE_SIZE);
|
||||
|
||||
if (probe_kernel_read(&i, (unsigned char *)va + DIO_IDOFF, 1)) {
|
||||
if (copy_from_kernel_nofault(&i,
|
||||
(unsigned char *)va + DIO_IDOFF, 1)) {
|
||||
if (scode >= DIOII_SCBASE)
|
||||
iounmap(va);
|
||||
continue; /* no board present at that select code */
|
||||
|
|
|
@ -1021,7 +1021,7 @@ static int __init hp_sdc_register(void)
|
|||
hp_sdc.base_io = (unsigned long) 0xf0428000;
|
||||
hp_sdc.data_io = (unsigned long) hp_sdc.base_io + 1;
|
||||
hp_sdc.status_io = (unsigned long) hp_sdc.base_io + 3;
|
||||
if (!probe_kernel_read(&i, (unsigned char *)hp_sdc.data_io, 1))
|
||||
if (!copy_from_kernel_nofault(&i, (unsigned char *)hp_sdc.data_io, 1))
|
||||
hp_sdc.dev = (void *)1;
|
||||
hp_sdc.dev_err = hp_sdc_init();
|
||||
#endif
|
||||
|
|
|
@ -828,7 +828,7 @@ static void run_plant_and_detach_test(int is_early)
|
|||
char before[BREAK_INSTR_SIZE];
|
||||
char after[BREAK_INSTR_SIZE];
|
||||
|
||||
probe_kernel_read(before, (char *)kgdbts_break_test,
|
||||
copy_from_kernel_nofault(before, (char *)kgdbts_break_test,
|
||||
BREAK_INSTR_SIZE);
|
||||
init_simple_test();
|
||||
ts.tst = plant_and_detach_test;
|
||||
|
@ -836,8 +836,8 @@ static void run_plant_and_detach_test(int is_early)
|
|||
/* Activate test with initial breakpoint */
|
||||
if (!is_early)
|
||||
kgdb_breakpoint();
|
||||
probe_kernel_read(after, (char *)kgdbts_break_test,
|
||||
BREAK_INSTR_SIZE);
|
||||
copy_from_kernel_nofault(after, (char *)kgdbts_break_test,
|
||||
BREAK_INSTR_SIZE);
|
||||
if (memcmp(before, after, BREAK_INSTR_SIZE)) {
|
||||
printk(KERN_CRIT "kgdbts: ERROR kgdb corrupted memory\n");
|
||||
panic("kgdb memory corruption");
|
||||
|
|
|
@ -402,7 +402,7 @@ int __init hpfb_init(void)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
err = probe_kernel_read(&i, (unsigned char *)INTFBVADDR + DIO_IDOFF, 1);
|
||||
err = copy_from_kernel_nofault(&i, (unsigned char *)INTFBVADDR + DIO_IDOFF, 1);
|
||||
|
||||
if (!err && (i == DIO_ID_FBUFFER) && topcat_sid_ok(sid = DIO_SECID(INTFBVADDR))) {
|
||||
if (!request_mem_region(INTFBPADDR, DIO_DEVSIZE, "Internal Topcat"))
|
||||
|
|
|
@ -512,7 +512,8 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
|
|||
* Using bounce buffer to bypass the
|
||||
* hardened user copy kernel text checks.
|
||||
*/
|
||||
if (probe_kernel_read(buf, (void *) start, tsz)) {
|
||||
if (copy_from_kernel_nofault(buf, (void *)start,
|
||||
tsz)) {
|
||||
if (clear_user(buffer, tsz)) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
|
|
|
@ -301,13 +301,14 @@ copy_struct_from_user(void *dst, size_t ksize, const void __user *src,
|
|||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
extern long probe_kernel_read(void *dst, const void *src, size_t size);
|
||||
extern long probe_user_read(void *dst, const void __user *src, size_t size);
|
||||
long copy_from_kernel_nofault(void *dst, const void *src, size_t size);
|
||||
long notrace copy_to_kernel_nofault(void *dst, const void *src, size_t size);
|
||||
|
||||
extern long notrace probe_kernel_write(void *dst, const void *src, size_t size);
|
||||
extern long notrace probe_user_write(void __user *dst, const void *src, size_t size);
|
||||
long copy_from_user_nofault(void *dst, const void __user *src, size_t size);
|
||||
long notrace copy_to_user_nofault(void __user *dst, const void *src,
|
||||
size_t size);
|
||||
|
||||
long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr,
|
||||
long count);
|
||||
|
@ -317,14 +318,16 @@ long strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
|
|||
long strnlen_user_nofault(const void __user *unsafe_addr, long count);
|
||||
|
||||
/**
|
||||
* probe_kernel_address(): safely attempt to read from a location
|
||||
* @addr: address to read from
|
||||
* @retval: read into this variable
|
||||
* get_kernel_nofault(): safely attempt to read from a location
|
||||
* @val: read into this variable
|
||||
* @ptr: address to read from
|
||||
*
|
||||
* Returns 0 on success, or -EFAULT.
|
||||
*/
|
||||
#define probe_kernel_address(addr, retval) \
|
||||
probe_kernel_read(&retval, addr, sizeof(retval))
|
||||
#define get_kernel_nofault(val, ptr) ({ \
|
||||
const typeof(val) *__gk_ptr = (ptr); \
|
||||
copy_from_kernel_nofault(&(val), __gk_ptr, sizeof(val));\
|
||||
})
|
||||
|
||||
#ifndef user_access_begin
|
||||
#define user_access_begin(ptr,len) access_ok(ptr, len)
|
||||
|
|
|
@ -169,18 +169,18 @@ int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
|
|||
{
|
||||
int err;
|
||||
|
||||
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;
|
||||
err = probe_kernel_write((char *)bpt->bpt_addr,
|
||||
err = copy_to_kernel_nofault((char *)bpt->bpt_addr,
|
||||
arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
|
||||
return err;
|
||||
}
|
||||
|
||||
int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
|
||||
{
|
||||
return probe_kernel_write((char *)bpt->bpt_addr,
|
||||
return copy_to_kernel_nofault((char *)bpt->bpt_addr,
|
||||
(char *)bpt->saved_instr, BREAK_INSTR_SIZE);
|
||||
}
|
||||
|
||||
|
|
|
@ -247,7 +247,7 @@ char *kgdb_mem2hex(char *mem, char *buf, int count)
|
|||
*/
|
||||
tmp = buf + count;
|
||||
|
||||
err = probe_kernel_read(tmp, mem, count);
|
||||
err = copy_from_kernel_nofault(tmp, mem, count);
|
||||
if (err)
|
||||
return NULL;
|
||||
while (count > 0) {
|
||||
|
@ -283,7 +283,7 @@ int kgdb_hex2mem(char *buf, char *mem, int count)
|
|||
*tmp_raw |= hex_to_bin(*tmp_hex--) << 4;
|
||||
}
|
||||
|
||||
return probe_kernel_write(mem, tmp_raw, count);
|
||||
return copy_to_kernel_nofault(mem, tmp_raw, count);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -335,7 +335,7 @@ static int kgdb_ebin2mem(char *buf, char *mem, int count)
|
|||
size++;
|
||||
}
|
||||
|
||||
return probe_kernel_write(mem, c, size);
|
||||
return copy_to_kernel_nofault(mem, c, size);
|
||||
}
|
||||
|
||||
#if DBG_MAX_REG_NUM > 0
|
||||
|
|
|
@ -2326,7 +2326,8 @@ void kdb_ps1(const struct task_struct *p)
|
|||
int cpu;
|
||||
unsigned long tmp;
|
||||
|
||||
if (!p || probe_kernel_read(&tmp, (char *)p, sizeof(unsigned long)))
|
||||
if (!p ||
|
||||
copy_from_kernel_nofault(&tmp, (char *)p, sizeof(unsigned long)))
|
||||
return;
|
||||
|
||||
cpu = kdb_process_cpu(p);
|
||||
|
|
|
@ -325,7 +325,7 @@ char *kdb_strdup(const char *str, gfp_t type)
|
|||
*/
|
||||
int kdb_getarea_size(void *res, unsigned long addr, size_t size)
|
||||
{
|
||||
int ret = probe_kernel_read((char *)res, (char *)addr, size);
|
||||
int ret = copy_from_kernel_nofault((char *)res, (char *)addr, size);
|
||||
if (ret) {
|
||||
if (!KDB_STATE(SUPPRESS)) {
|
||||
kdb_printf("kdb_getarea: Bad address 0x%lx\n", addr);
|
||||
|
@ -350,7 +350,7 @@ int kdb_getarea_size(void *res, unsigned long addr, size_t size)
|
|||
*/
|
||||
int kdb_putarea_size(unsigned long addr, void *res, size_t size)
|
||||
{
|
||||
int ret = probe_kernel_read((char *)addr, (char *)res, size);
|
||||
int ret = copy_from_kernel_nofault((char *)addr, (char *)res, size);
|
||||
if (ret) {
|
||||
if (!KDB_STATE(SUPPRESS)) {
|
||||
kdb_printf("kdb_putarea: Bad address 0x%lx\n", addr);
|
||||
|
@ -624,7 +624,8 @@ char kdb_task_state_char (const struct task_struct *p)
|
|||
char state;
|
||||
unsigned long tmp;
|
||||
|
||||
if (!p || probe_kernel_read(&tmp, (char *)p, sizeof(unsigned long)))
|
||||
if (!p ||
|
||||
copy_from_kernel_nofault(&tmp, (char *)p, sizeof(unsigned long)))
|
||||
return 'E';
|
||||
|
||||
cpu = kdb_process_cpu(p);
|
||||
|
|
|
@ -201,7 +201,7 @@ void *kthread_probe_data(struct task_struct *task)
|
|||
struct kthread *kthread = to_kthread(task);
|
||||
void *data = NULL;
|
||||
|
||||
probe_kernel_read(&data, &kthread->data, sizeof(data));
|
||||
copy_from_kernel_nofault(&data, &kthread->data, sizeof(data));
|
||||
return data;
|
||||
}
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ bpf_probe_read_user_common(void *dst, u32 size, const void __user *unsafe_ptr)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = probe_user_read(dst, unsafe_ptr, size);
|
||||
ret = copy_from_user_nofault(dst, unsafe_ptr, size);
|
||||
if (unlikely(ret < 0))
|
||||
memset(dst, 0, size);
|
||||
return ret;
|
||||
|
@ -196,7 +196,7 @@ bpf_probe_read_kernel_common(void *dst, u32 size, const void *unsafe_ptr)
|
|||
|
||||
if (unlikely(ret < 0))
|
||||
goto fail;
|
||||
ret = probe_kernel_read(dst, unsafe_ptr, size);
|
||||
ret = copy_from_kernel_nofault(dst, unsafe_ptr, size);
|
||||
if (unlikely(ret < 0))
|
||||
goto fail;
|
||||
return ret;
|
||||
|
@ -326,7 +326,7 @@ BPF_CALL_3(bpf_probe_write_user, void __user *, unsafe_ptr, const void *, src,
|
|||
if (unlikely(!nmi_uaccess_okay()))
|
||||
return -EPERM;
|
||||
|
||||
return probe_user_write(unsafe_ptr, src, size);
|
||||
return copy_to_user_nofault(unsafe_ptr, src, size);
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_probe_write_user_proto = {
|
||||
|
@ -661,7 +661,7 @@ BPF_CALL_5(bpf_seq_printf, struct seq_file *, m, char *, fmt, u32, fmt_size,
|
|||
|
||||
copy_size = (fmt[i + 2] == '4') ? 4 : 16;
|
||||
|
||||
err = probe_kernel_read(bufs->buf[memcpy_cnt],
|
||||
err = copy_from_kernel_nofault(bufs->buf[memcpy_cnt],
|
||||
(void *) (long) args[fmt_cnt],
|
||||
copy_size);
|
||||
if (err < 0)
|
||||
|
|
|
@ -1222,7 +1222,7 @@ fetch_store_strlen(unsigned long addr)
|
|||
#endif
|
||||
|
||||
do {
|
||||
ret = probe_kernel_read(&c, (u8 *)addr + len, 1);
|
||||
ret = copy_from_kernel_nofault(&c, (u8 *)addr + len, 1);
|
||||
len++;
|
||||
} while (c && ret == 0 && len < MAX_STRING_SIZE);
|
||||
|
||||
|
@ -1290,7 +1290,7 @@ probe_mem_read_user(void *dest, void *src, size_t size)
|
|||
{
|
||||
const void __user *uaddr = (__force const void __user *)src;
|
||||
|
||||
return probe_user_read(dest, uaddr, size);
|
||||
return copy_from_user_nofault(dest, uaddr, size);
|
||||
}
|
||||
|
||||
static nokprobe_inline int
|
||||
|
@ -1300,7 +1300,7 @@ probe_mem_read(void *dest, void *src, size_t size)
|
|||
if ((unsigned long)src < TASK_SIZE)
|
||||
return probe_mem_read_user(dest, src, size);
|
||||
#endif
|
||||
return probe_kernel_read(dest, src, size);
|
||||
return copy_from_kernel_nofault(dest, src, size);
|
||||
}
|
||||
|
||||
/* Note that we don't verify it, since the code does not come from user space */
|
||||
|
|
|
@ -4638,11 +4638,11 @@ void print_worker_info(const char *log_lvl, struct task_struct *task)
|
|||
* Carefully copy the associated workqueue's workfn, name and desc.
|
||||
* Keep the original last '\0' in case the original is garbage.
|
||||
*/
|
||||
probe_kernel_read(&fn, &worker->current_func, sizeof(fn));
|
||||
probe_kernel_read(&pwq, &worker->current_pwq, sizeof(pwq));
|
||||
probe_kernel_read(&wq, &pwq->wq, sizeof(wq));
|
||||
probe_kernel_read(name, wq->name, sizeof(name) - 1);
|
||||
probe_kernel_read(desc, worker->desc, sizeof(desc) - 1);
|
||||
copy_from_kernel_nofault(&fn, &worker->current_func, sizeof(fn));
|
||||
copy_from_kernel_nofault(&pwq, &worker->current_pwq, sizeof(pwq));
|
||||
copy_from_kernel_nofault(&wq, &pwq->wq, sizeof(wq));
|
||||
copy_from_kernel_nofault(name, wq->name, sizeof(name) - 1);
|
||||
copy_from_kernel_nofault(desc, worker->desc, sizeof(desc) - 1);
|
||||
|
||||
if (fn || name[0] || desc[0]) {
|
||||
printk("%sWorkqueue: %s %ps", log_lvl, name, fn);
|
||||
|
|
|
@ -419,8 +419,8 @@ static bool test_kernel_ptr(unsigned long addr, int size)
|
|||
/* should be at least readable kernel address */
|
||||
if (access_ok(ptr, 1) ||
|
||||
access_ok(ptr + size - 1, 1) ||
|
||||
probe_kernel_address(ptr, buf) ||
|
||||
probe_kernel_address(ptr + size - 1, buf)) {
|
||||
get_kernel_nofault(buf, ptr) ||
|
||||
get_kernel_nofault(buf, ptr + size - 1)) {
|
||||
pr_err("invalid kernel ptr: %#lx\n", addr);
|
||||
return true;
|
||||
}
|
||||
|
@ -437,7 +437,7 @@ static bool __maybe_unused test_magic(unsigned long addr, int offset,
|
|||
if (!addr)
|
||||
return false;
|
||||
|
||||
if (probe_kernel_address(ptr, magic) || magic != expected) {
|
||||
if (get_kernel_nofault(magic, ptr) || magic != expected) {
|
||||
pr_err("invalid magic at %#lx + %#x = %#x, expected %#x\n",
|
||||
addr, offset, magic, expected);
|
||||
return true;
|
||||
|
|
|
@ -120,9 +120,9 @@ void __dump_page(struct page *page, const char *reason)
|
|||
* mapping can be invalid pointer and we don't want to crash
|
||||
* accessing it, so probe everything depending on it carefully
|
||||
*/
|
||||
if (probe_kernel_read(&host, &mapping->host,
|
||||
if (copy_from_kernel_nofault(&host, &mapping->host,
|
||||
sizeof(struct inode *)) ||
|
||||
probe_kernel_read(&a_ops, &mapping->a_ops,
|
||||
copy_from_kernel_nofault(&a_ops, &mapping->a_ops,
|
||||
sizeof(struct address_space_operations *))) {
|
||||
pr_warn("failed to read mapping->host or a_ops, mapping not a valid kernel address?\n");
|
||||
goto out_mapping;
|
||||
|
@ -133,7 +133,7 @@ void __dump_page(struct page *page, const char *reason)
|
|||
goto out_mapping;
|
||||
}
|
||||
|
||||
if (probe_kernel_read(&dentry_first,
|
||||
if (copy_from_kernel_nofault(&dentry_first,
|
||||
&host->i_dentry.first, sizeof(struct hlist_node *))) {
|
||||
pr_warn("mapping->a_ops:%ps with invalid mapping->host inode address %px\n",
|
||||
a_ops, host);
|
||||
|
@ -146,7 +146,7 @@ void __dump_page(struct page *page, const char *reason)
|
|||
}
|
||||
|
||||
dentry_ptr = container_of(dentry_first, struct dentry, d_u.d_alias);
|
||||
if (probe_kernel_read(&dentry, dentry_ptr,
|
||||
if (copy_from_kernel_nofault(&dentry, dentry_ptr,
|
||||
sizeof(struct dentry))) {
|
||||
pr_warn("mapping->aops:%ps with invalid mapping->host->i_dentry.first %px\n",
|
||||
a_ops, dentry_ptr);
|
||||
|
|
61
mm/maccess.c
61
mm/maccess.c
|
@ -6,14 +6,15 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
bool __weak probe_kernel_read_allowed(const void *unsafe_src, size_t size)
|
||||
bool __weak copy_from_kernel_nofault_allowed(const void *unsafe_src,
|
||||
size_t size)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GET_KERNEL_NOFAULT
|
||||
|
||||
#define probe_kernel_read_loop(dst, src, len, type, err_label) \
|
||||
#define copy_from_kernel_nofault_loop(dst, src, len, type, err_label) \
|
||||
while (len >= sizeof(type)) { \
|
||||
__get_kernel_nofault(dst, src, type, err_label); \
|
||||
dst += sizeof(type); \
|
||||
|
@ -21,25 +22,25 @@ bool __weak probe_kernel_read_allowed(const void *unsafe_src, size_t size)
|
|||
len -= sizeof(type); \
|
||||
}
|
||||
|
||||
long probe_kernel_read(void *dst, const void *src, size_t size)
|
||||
long copy_from_kernel_nofault(void *dst, const void *src, size_t size)
|
||||
{
|
||||
if (!probe_kernel_read_allowed(src, size))
|
||||
if (!copy_from_kernel_nofault_allowed(src, size))
|
||||
return -ERANGE;
|
||||
|
||||
pagefault_disable();
|
||||
probe_kernel_read_loop(dst, src, size, u64, Efault);
|
||||
probe_kernel_read_loop(dst, src, size, u32, Efault);
|
||||
probe_kernel_read_loop(dst, src, size, u16, Efault);
|
||||
probe_kernel_read_loop(dst, src, size, u8, Efault);
|
||||
copy_from_kernel_nofault_loop(dst, src, size, u64, Efault);
|
||||
copy_from_kernel_nofault_loop(dst, src, size, u32, Efault);
|
||||
copy_from_kernel_nofault_loop(dst, src, size, u16, Efault);
|
||||
copy_from_kernel_nofault_loop(dst, src, size, u8, Efault);
|
||||
pagefault_enable();
|
||||
return 0;
|
||||
Efault:
|
||||
pagefault_enable();
|
||||
return -EFAULT;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(probe_kernel_read);
|
||||
EXPORT_SYMBOL_GPL(copy_from_kernel_nofault);
|
||||
|
||||
#define probe_kernel_write_loop(dst, src, len, type, err_label) \
|
||||
#define copy_to_kernel_nofault_loop(dst, src, len, type, err_label) \
|
||||
while (len >= sizeof(type)) { \
|
||||
__put_kernel_nofault(dst, src, type, err_label); \
|
||||
dst += sizeof(type); \
|
||||
|
@ -47,13 +48,13 @@ EXPORT_SYMBOL_GPL(probe_kernel_read);
|
|||
len -= sizeof(type); \
|
||||
}
|
||||
|
||||
long probe_kernel_write(void *dst, const void *src, size_t size)
|
||||
long copy_to_kernel_nofault(void *dst, const void *src, size_t size)
|
||||
{
|
||||
pagefault_disable();
|
||||
probe_kernel_write_loop(dst, src, size, u64, Efault);
|
||||
probe_kernel_write_loop(dst, src, size, u32, Efault);
|
||||
probe_kernel_write_loop(dst, src, size, u16, Efault);
|
||||
probe_kernel_write_loop(dst, src, size, u8, Efault);
|
||||
copy_to_kernel_nofault_loop(dst, src, size, u64, Efault);
|
||||
copy_to_kernel_nofault_loop(dst, src, size, u32, Efault);
|
||||
copy_to_kernel_nofault_loop(dst, src, size, u16, Efault);
|
||||
copy_to_kernel_nofault_loop(dst, src, size, u8, Efault);
|
||||
pagefault_enable();
|
||||
return 0;
|
||||
Efault:
|
||||
|
@ -67,7 +68,7 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
|
|||
|
||||
if (unlikely(count <= 0))
|
||||
return 0;
|
||||
if (!probe_kernel_read_allowed(unsafe_addr, count))
|
||||
if (!copy_from_kernel_nofault_allowed(unsafe_addr, count))
|
||||
return -ERANGE;
|
||||
|
||||
pagefault_disable();
|
||||
|
@ -87,7 +88,7 @@ Efault:
|
|||
}
|
||||
#else /* HAVE_GET_KERNEL_NOFAULT */
|
||||
/**
|
||||
* probe_kernel_read(): safely attempt to read from kernel-space
|
||||
* copy_from_kernel_nofault(): safely attempt to read from kernel-space
|
||||
* @dst: pointer to the buffer that shall take the data
|
||||
* @src: address to read from
|
||||
* @size: size of the data chunk
|
||||
|
@ -98,15 +99,15 @@ Efault:
|
|||
*
|
||||
* We ensure that the copy_from_user is executed in atomic context so that
|
||||
* do_page_fault() doesn't attempt to take mmap_lock. This makes
|
||||
* probe_kernel_read() suitable for use within regions where the caller
|
||||
* copy_from_kernel_nofault() suitable for use within regions where the caller
|
||||
* already holds mmap_lock, or other locks which nest inside mmap_lock.
|
||||
*/
|
||||
long probe_kernel_read(void *dst, const void *src, size_t size)
|
||||
long copy_from_kernel_nofault(void *dst, const void *src, size_t size)
|
||||
{
|
||||
long ret;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
if (!probe_kernel_read_allowed(src, size))
|
||||
if (!copy_from_kernel_nofault_allowed(src, size))
|
||||
return -ERANGE;
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
|
@ -120,10 +121,10 @@ long probe_kernel_read(void *dst, const void *src, size_t size)
|
|||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(probe_kernel_read);
|
||||
EXPORT_SYMBOL_GPL(copy_from_kernel_nofault);
|
||||
|
||||
/**
|
||||
* probe_kernel_write(): safely attempt to write to a location
|
||||
* copy_to_kernel_nofault(): safely attempt to write to a location
|
||||
* @dst: address to write to
|
||||
* @src: pointer to the data that shall be written
|
||||
* @size: size of the data chunk
|
||||
|
@ -131,7 +132,7 @@ EXPORT_SYMBOL_GPL(probe_kernel_read);
|
|||
* Safely write to address @dst from the buffer at @src. If a kernel fault
|
||||
* happens, handle that and return -EFAULT.
|
||||
*/
|
||||
long probe_kernel_write(void *dst, const void *src, size_t size)
|
||||
long copy_to_kernel_nofault(void *dst, const void *src, size_t size)
|
||||
{
|
||||
long ret;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
@ -174,7 +175,7 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
|
|||
|
||||
if (unlikely(count <= 0))
|
||||
return 0;
|
||||
if (!probe_kernel_read_allowed(unsafe_addr, count))
|
||||
if (!copy_from_kernel_nofault_allowed(unsafe_addr, count))
|
||||
return -ERANGE;
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
|
@ -193,7 +194,7 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
|
|||
#endif /* HAVE_GET_KERNEL_NOFAULT */
|
||||
|
||||
/**
|
||||
* probe_user_read(): safely attempt to read from a user-space location
|
||||
* copy_from_user_nofault(): safely attempt to read from a user-space location
|
||||
* @dst: pointer to the buffer that shall take the data
|
||||
* @src: address to read from. This must be a user address.
|
||||
* @size: size of the data chunk
|
||||
|
@ -201,7 +202,7 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
|
|||
* Safely read from user address @src to the buffer at @dst. If a kernel fault
|
||||
* happens, handle that and return -EFAULT.
|
||||
*/
|
||||
long probe_user_read(void *dst, const void __user *src, size_t size)
|
||||
long copy_from_user_nofault(void *dst, const void __user *src, size_t size)
|
||||
{
|
||||
long ret = -EFAULT;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
@ -218,10 +219,10 @@ long probe_user_read(void *dst, const void __user *src, size_t size)
|
|||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(probe_user_read);
|
||||
EXPORT_SYMBOL_GPL(copy_from_user_nofault);
|
||||
|
||||
/**
|
||||
* probe_user_write(): safely attempt to write to a user-space location
|
||||
* copy_to_user_nofault(): safely attempt to write to a user-space location
|
||||
* @dst: address to write to
|
||||
* @src: pointer to the data that shall be written
|
||||
* @size: size of the data chunk
|
||||
|
@ -229,7 +230,7 @@ EXPORT_SYMBOL_GPL(probe_user_read);
|
|||
* Safely write to address @dst from the buffer at @src. If a kernel fault
|
||||
* happens, handle that and return -EFAULT.
|
||||
*/
|
||||
long probe_user_write(void __user *dst, const void *src, size_t size)
|
||||
long copy_to_user_nofault(void __user *dst, const void *src, size_t size)
|
||||
{
|
||||
long ret = -EFAULT;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
@ -246,7 +247,7 @@ long probe_user_write(void __user *dst, const void *src, size_t size)
|
|||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(probe_user_write);
|
||||
EXPORT_SYMBOL_GPL(copy_to_user_nofault);
|
||||
|
||||
/**
|
||||
* strncpy_from_user_nofault: - Copy a NUL terminated string from unsafe user
|
||||
|
|
|
@ -25,7 +25,7 @@ void rodata_test(void)
|
|||
}
|
||||
|
||||
/* test 2: write to the variable; this should fault */
|
||||
if (!probe_kernel_write((void *)&rodata_test_data,
|
||||
if (!copy_to_kernel_nofault((void *)&rodata_test_data,
|
||||
(void *)&zero, sizeof(zero))) {
|
||||
pr_err("test data was not read only\n");
|
||||
return;
|
||||
|
|
|
@ -292,7 +292,7 @@ static inline void *get_freepointer_safe(struct kmem_cache *s, void *object)
|
|||
return get_freepointer(s, object);
|
||||
|
||||
freepointer_addr = (unsigned long)object + s->offset;
|
||||
probe_kernel_read(&p, (void **)freepointer_addr, sizeof(p));
|
||||
copy_from_kernel_nofault(&p, (void **)freepointer_addr, sizeof(p));
|
||||
return freelist_ptr(s, p, freepointer_addr);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче