mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	maccess: rename probe_kernel_{read,write} to copy_{from,to}_kernel_nofault
Better describe what these functions do. Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									b3a9e3b962
								
							
						
					
					
						commit
						fe557319aa
					
				
					 50 changed files with 138 additions and 122 deletions
				
			
		| 
						 | 
					@ -84,7 +84,8 @@ static int ftrace_modify_code(unsigned long pc, unsigned long old,
 | 
				
			||||||
		old = __opcode_to_mem_arm(old);
 | 
							old = __opcode_to_mem_arm(old);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (validate) {
 | 
						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;
 | 
								return -EFAULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (replaced != old)
 | 
							if (replaced != old)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -236,7 +236,7 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
 | 
				
			||||||
	/* patch_text() only supports int-sized breakpoints */
 | 
						/* patch_text() only supports int-sized breakpoints */
 | 
				
			||||||
	BUILD_BUG_ON(sizeof(int) != BREAK_INSTR_SIZE);
 | 
						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);
 | 
									BREAK_INSTR_SIZE);
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,7 +135,7 @@ int __kprobes aarch64_insn_read(void *addr, u32 *insnp)
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
	__le32 val;
 | 
						__le32 val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = probe_kernel_read(&val, addr, AARCH64_INSN_SIZE);
 | 
						ret = copy_from_kernel_nofault(&val, addr, AARCH64_INSN_SIZE);
 | 
				
			||||||
	if (!ret)
 | 
						if (!ret)
 | 
				
			||||||
		*insnp = le32_to_cpu(val);
 | 
							*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);
 | 
						raw_spin_lock_irqsave(&patch_lock, flags);
 | 
				
			||||||
	waddr = patch_map(addr, FIX_TEXT_POKE0);
 | 
						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);
 | 
						patch_unmap(FIX_TEXT_POKE0);
 | 
				
			||||||
	raw_spin_unlock_irqrestore(&patch_lock, flags);
 | 
						raw_spin_unlock_irqrestore(&patch_lock, flags);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -72,7 +72,8 @@ static int ftrace_check_current_nop(unsigned long hook)
 | 
				
			||||||
	uint16_t olds[7];
 | 
						uint16_t olds[7];
 | 
				
			||||||
	unsigned long hook_pos = hook - 2;
 | 
						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;
 | 
							return -EFAULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (memcmp((void *)nops, (void *)olds, sizeof(nops))) {
 | 
						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);
 | 
						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));
 | 
									 sizeof(nops));
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return -EPERM;
 | 
							return -EPERM;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,7 +108,7 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code,
 | 
				
			||||||
		goto skip_check;
 | 
							goto skip_check;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* read the text we want to modify */
 | 
						/* 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;
 | 
							return -EFAULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Make sure it is what we expect it to be */
 | 
						/* 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:
 | 
					skip_check:
 | 
				
			||||||
	/* replace the text with the new text */
 | 
						/* 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;
 | 
							return -EPERM;
 | 
				
			||||||
	flush_icache_range(ip, ip + MCOUNT_INSN_SIZE);
 | 
						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 char __attribute__((aligned(8))) replaced[MCOUNT_INSN_SIZE];
 | 
				
			||||||
	unsigned long ip = rec->ip;
 | 
						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;
 | 
							return -EFAULT;
 | 
				
			||||||
	if (rec->flags & FTRACE_FL_CONVERTED) {
 | 
						if (rec->flags & FTRACE_FL_CONVERTED) {
 | 
				
			||||||
		struct ftrace_call_insn *call_insn, *tmp_call;
 | 
							struct ftrace_call_insn *call_insn, *tmp_call;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,9 +86,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((probe_kernel_read(&prev_insn, p->addr - 1,
 | 
						if (copy_from_kernel_nofault(&prev_insn, p->addr - 1,
 | 
				
			||||||
				sizeof(mips_instruction)) == 0) &&
 | 
								sizeof(mips_instruction)) == 0 &&
 | 
				
			||||||
				insn_has_delayslot(prev_insn)) {
 | 
						    insn_has_delayslot(prev_insn)) {
 | 
				
			||||||
		pr_notice("Kprobes for branch delayslot are not supported\n");
 | 
							pr_notice("Kprobes for branch delayslot are not supported\n");
 | 
				
			||||||
		ret = -EINVAL;
 | 
							ret = -EINVAL;
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -131,13 +131,14 @@ static int __ftrace_modify_code(unsigned long pc, unsigned long *old_insn,
 | 
				
			||||||
	unsigned long orig_insn[3];
 | 
						unsigned long orig_insn[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (validate) {
 | 
						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;
 | 
								return -EFAULT;
 | 
				
			||||||
		if (memcmp(orig_insn, old_insn, MCOUNT_INSN_SIZE))
 | 
							if (memcmp(orig_insn, old_insn, MCOUNT_INSN_SIZE))
 | 
				
			||||||
			return -EINVAL;
 | 
								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 -EPERM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -172,7 +172,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ip = (void *)(rec->ip + 4 - size);
 | 
						ip = (void *)(rec->ip + 4 - size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = probe_kernel_read(insn, ip, size);
 | 
						ret = copy_from_kernel_nofault(insn, ip, size);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return 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 kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
 | 
						int ret = copy_from_kernel_nofault(bpt->saved_instr,
 | 
				
			||||||
				BREAK_INSTR_SIZE);
 | 
								(char *)bpt->bpt_addr, BREAK_INSTR_SIZE);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ void * memcpy(void * dst,const void *src, size_t count)
 | 
				
			||||||
EXPORT_SYMBOL(raw_copy_in_user);
 | 
					EXPORT_SYMBOL(raw_copy_in_user);
 | 
				
			||||||
EXPORT_SYMBOL(memcpy);
 | 
					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)
 | 
						if ((unsigned long)unsafe_src < PAGE_SIZE)
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -756,7 +756,8 @@ int module_trampoline_target(struct module *mod, unsigned long addr,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	stub = (struct ppc64_stub_entry *)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);
 | 
							pr_err("%s: fault reading magic for stub %lx for %s\n", __func__, addr, mod->name);
 | 
				
			||||||
		return -EFAULT;
 | 
							return -EFAULT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -766,7 +767,8 @@ int module_trampoline_target(struct module *mod, unsigned long addr,
 | 
				
			||||||
		return -EFAULT;
 | 
							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);
 | 
							pr_err("%s: fault reading funcdata for stub %lx for %s\n", __func__, addr, mod->name);
 | 
				
			||||||
                return -EFAULT;
 | 
					                return -EFAULT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -226,7 +226,7 @@ __ftrace_make_nop(struct module *mod,
 | 
				
			||||||
	unsigned long ip = rec->ip;
 | 
						unsigned long ip = rec->ip;
 | 
				
			||||||
	unsigned long tramp;
 | 
						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;
 | 
							return -EFAULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Make sure that that this is still a 24bit jump */
 | 
						/* 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);
 | 
						pr_devel("ip:%lx jumps to %lx", ip, tramp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Find where the trampoline jumps to */
 | 
						/* 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);
 | 
							pr_err("Failed to read %lx\n", tramp);
 | 
				
			||||||
		return -EFAULT;
 | 
							return -EFAULT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,11 +33,11 @@ int probe_kernel_read_inst(struct ppc_inst *inst,
 | 
				
			||||||
	unsigned int val, suffix;
 | 
						unsigned int val, suffix;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = probe_kernel_read(&val, src, sizeof(val));
 | 
						err = copy_from_kernel_nofault(&val, src, sizeof(val));
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
	if (get_op(val) == OP_PREFIX) {
 | 
						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);
 | 
							*inst = ppc_inst_prefix(val, suffix);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		*inst = ppc_inst(val);
 | 
							*inst = ppc_inst(val);
 | 
				
			||||||
| 
						 | 
					@ -64,7 +64,7 @@ int probe_kernel_read_inst(struct ppc_inst *inst,
 | 
				
			||||||
	unsigned int val;
 | 
						unsigned int val;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = probe_kernel_read(&val, src, sizeof(val));
 | 
						err = copy_from_kernel_nofault(&val, src, sizeof(val));
 | 
				
			||||||
	if (!err)
 | 
						if (!err)
 | 
				
			||||||
		*inst = ppc_inst(val);
 | 
							*inst = ppc_inst(val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -418,7 +418,8 @@ static __u64 power_pmu_bhrb_to(u64 addr)
 | 
				
			||||||
	__u64 target;
 | 
						__u64 target;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (is_kernel_addr(addr)) {
 | 
						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 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return branch_target((struct ppc_inst *)&instr);
 | 
							return branch_target((struct ppc_inst *)&instr);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,7 +38,8 @@ static int ftrace_check_current_call(unsigned long hook_pos,
 | 
				
			||||||
	 * Read the text we want to modify;
 | 
						 * Read the text we want to modify;
 | 
				
			||||||
	 * return must be -EFAULT on read error
 | 
						 * 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;
 | 
							return -EFAULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -153,7 +153,7 @@ int do_single_step(struct pt_regs *regs)
 | 
				
			||||||
	stepped_address = addr;
 | 
						stepped_address = addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Replace the op code with the break instruction */
 | 
						/* 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,
 | 
									   arch_kgdb_ops.gdb_bpt_instr,
 | 
				
			||||||
				   BREAK_INSTR_SIZE);
 | 
									   BREAK_INSTR_SIZE);
 | 
				
			||||||
	/* Flush and return */
 | 
						/* Flush and return */
 | 
				
			||||||
| 
						 | 
					@ -173,7 +173,7 @@ int do_single_step(struct pt_regs *regs)
 | 
				
			||||||
static void undo_single_step(struct pt_regs *regs)
 | 
					static void undo_single_step(struct pt_regs *regs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (stepped_opcode != 0) {
 | 
						if (stepped_opcode != 0) {
 | 
				
			||||||
		probe_kernel_write((void *)stepped_address,
 | 
							copy_to_kernel_nofault((void *)stepped_address,
 | 
				
			||||||
				   (void *)&stepped_opcode, BREAK_INSTR_SIZE);
 | 
									   (void *)&stepped_opcode, BREAK_INSTR_SIZE);
 | 
				
			||||||
		flush_icache_range(stepped_address,
 | 
							flush_icache_range(stepped_address,
 | 
				
			||||||
				   stepped_address + BREAK_INSTR_SIZE);
 | 
									   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);
 | 
						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);
 | 
						patch_unmap(FIX_TEXT_POKE0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -76,7 +76,7 @@ NOKPROBE_SYMBOL(patch_insn_write);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
static int patch_insn_write(void *addr, const void *insn, size_t len)
 | 
					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);
 | 
					NOKPROBE_SYMBOL(patch_insn_write);
 | 
				
			||||||
#endif /* CONFIG_MMU */
 | 
					#endif /* CONFIG_MMU */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,7 +83,7 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ftrace_insn orig, new, old;
 | 
						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;
 | 
							return -EFAULT;
 | 
				
			||||||
	if (addr == MCOUNT_ADDR) {
 | 
						if (addr == MCOUNT_ADDR) {
 | 
				
			||||||
		/* Initial code replacement */
 | 
							/* Initial code replacement */
 | 
				
			||||||
| 
						 | 
					@ -105,7 +105,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ftrace_insn orig, new, old;
 | 
						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;
 | 
							return -EFAULT;
 | 
				
			||||||
	/* Replace nop with an ftrace call. */
 | 
						/* Replace nop with an ftrace call. */
 | 
				
			||||||
	ftrace_generate_nop_insn(&orig);
 | 
						ftrace_generate_nop_insn(&orig);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -119,7 +119,7 @@ static void ftrace_mod_code(void)
 | 
				
			||||||
	 * But if one were to fail, then they all should, and if one were
 | 
						 * But if one were to fail, then they all should, and if one were
 | 
				
			||||||
	 * to succeed, then they all should.
 | 
						 * 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);
 | 
										     MCOUNT_INSN_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* if we fail, then kill any new writers */
 | 
						/* 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 */
 | 
						/* 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;
 | 
							return -EFAULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Make sure it is what we expect it to be */
 | 
						/* 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];
 | 
						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;
 | 
							return -EFAULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (old_addr != __raw_readl((unsigned long *)code))
 | 
						if (old_addr != __raw_readl((unsigned long *)code))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@
 | 
				
			||||||
#include <linux/kernel.h>
 | 
					#include <linux/kernel.h>
 | 
				
			||||||
#include <os.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);
 | 
						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 */
 | 
					/* 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
 | 
					 * 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);
 | 
						addr = regs_get_kernel_stack_nth_addr(regs, n);
 | 
				
			||||||
	if (addr) {
 | 
						if (addr) {
 | 
				
			||||||
		ret = probe_kernel_read(&val, addr, sizeof(val));
 | 
							ret = copy_from_kernel_nofault(&val, addr, sizeof(val));
 | 
				
			||||||
		if (!ret)
 | 
							if (!ret)
 | 
				
			||||||
			return val;
 | 
								return val;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,7 +106,7 @@ void show_opcodes(struct pt_regs *regs, const char *loglvl)
 | 
				
			||||||
	bad_ip = user_mode(regs) &&
 | 
						bad_ip = user_mode(regs) &&
 | 
				
			||||||
		__chk_range_not_ok(prologue, OPCODE_BUFSIZE, TASK_SIZE_MAX);
 | 
							__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)) {
 | 
										OPCODE_BUFSIZE)) {
 | 
				
			||||||
		printk("%sCode: Bad RIP value.\n", loglvl);
 | 
							printk("%sCode: Bad RIP value.\n", loglvl);
 | 
				
			||||||
	} else {
 | 
						} 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.
 | 
						 * sure what we read is what we expected it to be before modifying it.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	/* read the text we want to modify */
 | 
						/* 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);
 | 
							WARN_ON(1);
 | 
				
			||||||
		return -EFAULT;
 | 
							return -EFAULT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -355,7 +355,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
 | 
				
			||||||
	npages = DIV_ROUND_UP(*tramp_size, PAGE_SIZE);
 | 
						npages = DIV_ROUND_UP(*tramp_size, PAGE_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Copy ftrace_caller onto the trampoline memory */
 | 
						/* 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))
 | 
						if (WARN_ON(ret < 0))
 | 
				
			||||||
		goto fail;
 | 
							goto fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -363,13 +363,13 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* The trampoline ends with ret(q) */
 | 
						/* The trampoline ends with ret(q) */
 | 
				
			||||||
	retq = (unsigned long)ftrace_stub;
 | 
						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))
 | 
						if (WARN_ON(ret < 0))
 | 
				
			||||||
		goto fail;
 | 
							goto fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) {
 | 
						if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) {
 | 
				
			||||||
		ip = trampoline + (ftrace_regs_caller_ret - ftrace_regs_caller);
 | 
							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))
 | 
							if (WARN_ON(ret < 0))
 | 
				
			||||||
			goto fail;
 | 
								goto fail;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -506,7 +506,7 @@ static void *addr_from_call(void *ptr)
 | 
				
			||||||
	union text_poke_insn call;
 | 
						union text_poke_insn call;
 | 
				
			||||||
	int ret;
 | 
						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))
 | 
						if (WARN_ON_ONCE(ret < 0))
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -732,11 +732,11 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bpt->type = BP_BREAKPOINT;
 | 
						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);
 | 
									BREAK_INSTR_SIZE);
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		return 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);
 | 
									 arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
 | 
				
			||||||
	if (!err)
 | 
						if (!err)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
| 
						 | 
					@ -768,7 +768,7 @@ int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
knl_write:
 | 
					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);
 | 
									  (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
 | 
						 * Fortunately, we know that the original code is the ideal 5-byte
 | 
				
			||||||
	 * long NOP.
 | 
						 * long NOP.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (probe_kernel_read(buf, (void *)addr,
 | 
						if (copy_from_kernel_nofault(buf, (void *)addr,
 | 
				
			||||||
		MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
 | 
							MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
 | 
				
			||||||
		return 0UL;
 | 
							return 0UL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -346,7 +346,8 @@ int __copy_instruction(u8 *dest, u8 *src, u8 *real, struct insn *insn)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* This can access kernel text if given address is not recovered */
 | 
						/* 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;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kernel_insn_init(insn, dest, MAX_INSN_SIZE);
 | 
						kernel_insn_init(insn, dest, MAX_INSN_SIZE);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,7 +56,7 @@ unsigned long __recover_optprobed_insn(kprobe_opcode_t *buf, unsigned long addr)
 | 
				
			||||||
	 * overwritten by jump destination address. In this case, original
 | 
						 * overwritten by jump destination address. In this case, original
 | 
				
			||||||
	 * bytes must be recovered from op->optinsn.copied_insn buffer.
 | 
						 * 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)))
 | 
							MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
 | 
				
			||||||
		return 0UL;
 | 
							return 0UL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -488,7 +488,8 @@ static enum kernel_gp_hint get_kernel_gp_address(struct pt_regs *regs,
 | 
				
			||||||
	u8 insn_buf[MAX_INSN_SIZE];
 | 
						u8 insn_buf[MAX_INSN_SIZE];
 | 
				
			||||||
	struct insn insn;
 | 
						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;
 | 
							return GP_NO_HINT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kernel_insn_init(&insn, insn_buf, MAX_INSN_SIZE);
 | 
						kernel_insn_init(&insn, insn_buf, MAX_INSN_SIZE);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -442,7 +442,7 @@ static void show_ldttss(const struct desc_ptr *gdt, const char *name, u16 index)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (probe_kernel_read(&desc, (void *)(gdt->address + offset),
 | 
						if (copy_from_kernel_nofault(&desc, (void *)(gdt->address + offset),
 | 
				
			||||||
			      sizeof(struct ldttss_desc))) {
 | 
								      sizeof(struct ldttss_desc))) {
 | 
				
			||||||
		pr_alert("%s: 0x%hx -- GDT entry is not readable\n",
 | 
							pr_alert("%s: 0x%hx -- GDT entry is not readable\n",
 | 
				
			||||||
			 name, index);
 | 
								 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);
 | 
						__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);
 | 
							clear_fixmap(FIX_WP_TEST);
 | 
				
			||||||
		printk(KERN_CONT "Ok.\n");
 | 
							printk(KERN_CONT "Ok.\n");
 | 
				
			||||||
		return;
 | 
							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);
 | 
						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;
 | 
						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;
 | 
						       canonical_address(vaddr, boot_cpu_data.x86_virt_bits) == vaddr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#else
 | 
					#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;
 | 
						return (unsigned long)unsafe_src >= TASK_SIZE_MAX;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -386,7 +386,7 @@ static void set_aliased_prot(void *v, pgprot_t prot)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	preempt_disable();
 | 
						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))
 | 
						if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0))
 | 
				
			||||||
		BUG();
 | 
							BUG();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -171,7 +171,7 @@ static ssize_t read_mem(struct file *file, char __user *buf,
 | 
				
			||||||
			if (!ptr)
 | 
								if (!ptr)
 | 
				
			||||||
				goto failed;
 | 
									goto failed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			probe = probe_kernel_read(bounce, ptr, sz);
 | 
								probe = copy_from_kernel_nofault(bounce, ptr, sz);
 | 
				
			||||||
			unxlate_dev_mem_ptr(p, ptr);
 | 
								unxlate_dev_mem_ptr(p, ptr);
 | 
				
			||||||
			if (probe)
 | 
								if (probe)
 | 
				
			||||||
				goto failed;
 | 
									goto failed;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,7 +135,8 @@ int __init dio_find(int deviceid)
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			va = ioremap(pa, PAGE_SIZE);
 | 
								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)
 | 
								if (scode >= DIOII_SCBASE)
 | 
				
			||||||
				iounmap(va);
 | 
									iounmap(va);
 | 
				
			||||||
                        continue;             /* no board present at that select code */
 | 
					                        continue;             /* no board present at that select code */
 | 
				
			||||||
| 
						 | 
					@ -208,7 +209,8 @@ static int __init dio_init(void)
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			va = ioremap(pa, PAGE_SIZE);
 | 
								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)
 | 
								if (scode >= DIOII_SCBASE)
 | 
				
			||||||
				iounmap(va);
 | 
									iounmap(va);
 | 
				
			||||||
                        continue;              /* no board present at that select code */
 | 
					                        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.base_io	 = (unsigned long) 0xf0428000;
 | 
				
			||||||
	hp_sdc.data_io	 = (unsigned long) hp_sdc.base_io + 1;
 | 
						hp_sdc.data_io	 = (unsigned long) hp_sdc.base_io + 1;
 | 
				
			||||||
	hp_sdc.status_io = (unsigned long) hp_sdc.base_io + 3;
 | 
						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 = (void *)1;
 | 
				
			||||||
	hp_sdc.dev_err   = hp_sdc_init();
 | 
						hp_sdc.dev_err   = hp_sdc_init();
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -828,7 +828,7 @@ static void run_plant_and_detach_test(int is_early)
 | 
				
			||||||
	char before[BREAK_INSTR_SIZE];
 | 
						char before[BREAK_INSTR_SIZE];
 | 
				
			||||||
	char after[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);
 | 
						  BREAK_INSTR_SIZE);
 | 
				
			||||||
	init_simple_test();
 | 
						init_simple_test();
 | 
				
			||||||
	ts.tst = plant_and_detach_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 */
 | 
						/* Activate test with initial breakpoint */
 | 
				
			||||||
	if (!is_early)
 | 
						if (!is_early)
 | 
				
			||||||
		kgdb_breakpoint();
 | 
							kgdb_breakpoint();
 | 
				
			||||||
	probe_kernel_read(after, (char *)kgdbts_break_test,
 | 
						copy_from_kernel_nofault(after, (char *)kgdbts_break_test,
 | 
				
			||||||
	  BREAK_INSTR_SIZE);
 | 
								BREAK_INSTR_SIZE);
 | 
				
			||||||
	if (memcmp(before, after, BREAK_INSTR_SIZE)) {
 | 
						if (memcmp(before, after, BREAK_INSTR_SIZE)) {
 | 
				
			||||||
		printk(KERN_CRIT "kgdbts: ERROR kgdb corrupted memory\n");
 | 
							printk(KERN_CRIT "kgdbts: ERROR kgdb corrupted memory\n");
 | 
				
			||||||
		panic("kgdb memory corruption");
 | 
							panic("kgdb memory corruption");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -402,7 +402,7 @@ int __init hpfb_init(void)
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		return 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 (!err && (i == DIO_ID_FBUFFER) && topcat_sid_ok(sid = DIO_SECID(INTFBVADDR))) {
 | 
				
			||||||
		if (!request_mem_region(INTFBPADDR, DIO_DEVSIZE, "Internal Topcat"))
 | 
							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
 | 
									 * Using bounce buffer to bypass the
 | 
				
			||||||
				 * hardened user copy kernel text checks.
 | 
									 * 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)) {
 | 
										if (clear_user(buffer, tsz)) {
 | 
				
			||||||
						ret = -EFAULT;
 | 
											ret = -EFAULT;
 | 
				
			||||||
						goto out;
 | 
											goto out;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -301,13 +301,14 @@ copy_struct_from_user(void *dst, size_t ksize, const void __user *src,
 | 
				
			||||||
	return 0;
 | 
						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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 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);
 | 
					extern long probe_user_read(void *dst, const void __user *src, size_t size);
 | 
				
			||||||
 | 
					extern long notrace probe_user_write(void __user *dst, const void *src,
 | 
				
			||||||
extern long notrace probe_kernel_write(void *dst, const void *src, size_t size);
 | 
							size_t size);
 | 
				
			||||||
extern long notrace probe_user_write(void __user *dst, const void *src, size_t size);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr,
 | 
					long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr,
 | 
				
			||||||
		long count);
 | 
							long count);
 | 
				
			||||||
| 
						 | 
					@ -324,7 +325,7 @@ long strnlen_user_nofault(const void __user *unsafe_addr, long count);
 | 
				
			||||||
 * Returns 0 on success, or -EFAULT.
 | 
					 * Returns 0 on success, or -EFAULT.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#define probe_kernel_address(addr, retval)		\
 | 
					#define probe_kernel_address(addr, retval)		\
 | 
				
			||||||
	probe_kernel_read(&retval, addr, sizeof(retval))
 | 
						copy_from_kernel_nofault(&retval, addr, sizeof(retval))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef user_access_begin
 | 
					#ifndef user_access_begin
 | 
				
			||||||
#define user_access_begin(ptr,len) access_ok(ptr, len)
 | 
					#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;
 | 
						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);
 | 
									BREAK_INSTR_SIZE);
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		return 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);
 | 
									 arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
 | 
					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);
 | 
									  (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -247,7 +247,7 @@ char *kgdb_mem2hex(char *mem, char *buf, int count)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	tmp = buf + count;
 | 
						tmp = buf + count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = probe_kernel_read(tmp, mem, count);
 | 
						err = copy_from_kernel_nofault(tmp, mem, count);
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	while (count > 0) {
 | 
						while (count > 0) {
 | 
				
			||||||
| 
						 | 
					@ -283,7 +283,7 @@ int kgdb_hex2mem(char *buf, char *mem, int count)
 | 
				
			||||||
		*tmp_raw |= hex_to_bin(*tmp_hex--) << 4;
 | 
							*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++;
 | 
							size++;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return probe_kernel_write(mem, c, size);
 | 
						return copy_to_kernel_nofault(mem, c, size);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if DBG_MAX_REG_NUM > 0
 | 
					#if DBG_MAX_REG_NUM > 0
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2326,7 +2326,8 @@ void kdb_ps1(const struct task_struct *p)
 | 
				
			||||||
	int cpu;
 | 
						int cpu;
 | 
				
			||||||
	unsigned long tmp;
 | 
						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;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cpu = kdb_process_cpu(p);
 | 
						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 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 (ret) {
 | 
				
			||||||
		if (!KDB_STATE(SUPPRESS)) {
 | 
							if (!KDB_STATE(SUPPRESS)) {
 | 
				
			||||||
			kdb_printf("kdb_getarea: Bad address 0x%lx\n", addr);
 | 
								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 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 (ret) {
 | 
				
			||||||
		if (!KDB_STATE(SUPPRESS)) {
 | 
							if (!KDB_STATE(SUPPRESS)) {
 | 
				
			||||||
			kdb_printf("kdb_putarea: Bad address 0x%lx\n", addr);
 | 
								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;
 | 
						char state;
 | 
				
			||||||
	unsigned long tmp;
 | 
						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';
 | 
							return 'E';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cpu = kdb_process_cpu(p);
 | 
						cpu = kdb_process_cpu(p);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -201,7 +201,7 @@ void *kthread_probe_data(struct task_struct *task)
 | 
				
			||||||
	struct kthread *kthread = to_kthread(task);
 | 
						struct kthread *kthread = to_kthread(task);
 | 
				
			||||||
	void *data = NULL;
 | 
						void *data = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	probe_kernel_read(&data, &kthread->data, sizeof(data));
 | 
						copy_from_kernel_nofault(&data, &kthread->data, sizeof(data));
 | 
				
			||||||
	return data;
 | 
						return data;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -196,7 +196,7 @@ bpf_probe_read_kernel_common(void *dst, u32 size, const void *unsafe_ptr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (unlikely(ret < 0))
 | 
						if (unlikely(ret < 0))
 | 
				
			||||||
		goto fail;
 | 
							goto fail;
 | 
				
			||||||
	ret = probe_kernel_read(dst, unsafe_ptr, size);
 | 
						ret = copy_from_kernel_nofault(dst, unsafe_ptr, size);
 | 
				
			||||||
	if (unlikely(ret < 0))
 | 
						if (unlikely(ret < 0))
 | 
				
			||||||
		goto fail;
 | 
							goto fail;
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
								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],
 | 
											(void *) (long) args[fmt_cnt],
 | 
				
			||||||
						copy_size);
 | 
											copy_size);
 | 
				
			||||||
			if (err < 0)
 | 
								if (err < 0)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1222,7 +1222,7 @@ fetch_store_strlen(unsigned long addr)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	do {
 | 
						do {
 | 
				
			||||||
		ret = probe_kernel_read(&c, (u8 *)addr + len, 1);
 | 
							ret = copy_from_kernel_nofault(&c, (u8 *)addr + len, 1);
 | 
				
			||||||
		len++;
 | 
							len++;
 | 
				
			||||||
	} while (c && ret == 0 && len < MAX_STRING_SIZE);
 | 
						} while (c && ret == 0 && len < MAX_STRING_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1300,7 +1300,7 @@ probe_mem_read(void *dest, void *src, size_t size)
 | 
				
			||||||
	if ((unsigned long)src < TASK_SIZE)
 | 
						if ((unsigned long)src < TASK_SIZE)
 | 
				
			||||||
		return probe_mem_read_user(dest, src, size);
 | 
							return probe_mem_read_user(dest, src, size);
 | 
				
			||||||
#endif
 | 
					#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 */
 | 
					/* 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.
 | 
						 * Carefully copy the associated workqueue's workfn, name and desc.
 | 
				
			||||||
	 * Keep the original last '\0' in case the original is garbage.
 | 
						 * Keep the original last '\0' in case the original is garbage.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	probe_kernel_read(&fn, &worker->current_func, sizeof(fn));
 | 
						copy_from_kernel_nofault(&fn, &worker->current_func, sizeof(fn));
 | 
				
			||||||
	probe_kernel_read(&pwq, &worker->current_pwq, sizeof(pwq));
 | 
						copy_from_kernel_nofault(&pwq, &worker->current_pwq, sizeof(pwq));
 | 
				
			||||||
	probe_kernel_read(&wq, &pwq->wq, sizeof(wq));
 | 
						copy_from_kernel_nofault(&wq, &pwq->wq, sizeof(wq));
 | 
				
			||||||
	probe_kernel_read(name, wq->name, sizeof(name) - 1);
 | 
						copy_from_kernel_nofault(name, wq->name, sizeof(name) - 1);
 | 
				
			||||||
	probe_kernel_read(desc, worker->desc, sizeof(desc) - 1);
 | 
						copy_from_kernel_nofault(desc, worker->desc, sizeof(desc) - 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (fn || name[0] || desc[0]) {
 | 
						if (fn || name[0] || desc[0]) {
 | 
				
			||||||
		printk("%sWorkqueue: %s %ps", log_lvl, name, fn);
 | 
							printk("%sWorkqueue: %s %ps", log_lvl, name, fn);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
							 * mapping can be invalid pointer and we don't want to crash
 | 
				
			||||||
		 * accessing it, so probe everything depending on it carefully
 | 
							 * 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 *)) ||
 | 
										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 *))) {
 | 
									sizeof(struct address_space_operations *))) {
 | 
				
			||||||
			pr_warn("failed to read mapping->host or a_ops, mapping not a valid kernel address?\n");
 | 
								pr_warn("failed to read mapping->host or a_ops, mapping not a valid kernel address?\n");
 | 
				
			||||||
			goto out_mapping;
 | 
								goto out_mapping;
 | 
				
			||||||
| 
						 | 
					@ -133,7 +133,7 @@ void __dump_page(struct page *page, const char *reason)
 | 
				
			||||||
			goto out_mapping;
 | 
								goto out_mapping;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (probe_kernel_read(&dentry_first,
 | 
							if (copy_from_kernel_nofault(&dentry_first,
 | 
				
			||||||
			&host->i_dentry.first, sizeof(struct hlist_node *))) {
 | 
								&host->i_dentry.first, sizeof(struct hlist_node *))) {
 | 
				
			||||||
			pr_warn("mapping->a_ops:%ps with invalid mapping->host inode address %px\n",
 | 
								pr_warn("mapping->a_ops:%ps with invalid mapping->host inode address %px\n",
 | 
				
			||||||
				a_ops, host);
 | 
									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);
 | 
							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))) {
 | 
												sizeof(struct dentry))) {
 | 
				
			||||||
			pr_warn("mapping->aops:%ps with invalid mapping->host->i_dentry.first %px\n",
 | 
								pr_warn("mapping->aops:%ps with invalid mapping->host->i_dentry.first %px\n",
 | 
				
			||||||
				a_ops, dentry_ptr);
 | 
									a_ops, dentry_ptr);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										49
									
								
								mm/maccess.c
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								mm/maccess.c
									
									
									
									
									
								
							| 
						 | 
					@ -6,14 +6,15 @@
 | 
				
			||||||
#include <linux/mm.h>
 | 
					#include <linux/mm.h>
 | 
				
			||||||
#include <linux/uaccess.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;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_GET_KERNEL_NOFAULT
 | 
					#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)) {					\
 | 
						while (len >= sizeof(type)) {					\
 | 
				
			||||||
		__get_kernel_nofault(dst, src, type, err_label);		\
 | 
							__get_kernel_nofault(dst, src, type, err_label);		\
 | 
				
			||||||
		dst += sizeof(type);					\
 | 
							dst += sizeof(type);					\
 | 
				
			||||||
| 
						 | 
					@ -21,25 +22,25 @@ bool __weak probe_kernel_read_allowed(const void *unsafe_src, size_t size)
 | 
				
			||||||
		len -= sizeof(type);					\
 | 
							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;
 | 
							return -ERANGE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pagefault_disable();
 | 
						pagefault_disable();
 | 
				
			||||||
	probe_kernel_read_loop(dst, src, size, u64, Efault);
 | 
						copy_from_kernel_nofault_loop(dst, src, size, u64, Efault);
 | 
				
			||||||
	probe_kernel_read_loop(dst, src, size, u32, Efault);
 | 
						copy_from_kernel_nofault_loop(dst, src, size, u32, Efault);
 | 
				
			||||||
	probe_kernel_read_loop(dst, src, size, u16, Efault);
 | 
						copy_from_kernel_nofault_loop(dst, src, size, u16, Efault);
 | 
				
			||||||
	probe_kernel_read_loop(dst, src, size, u8, Efault);
 | 
						copy_from_kernel_nofault_loop(dst, src, size, u8, Efault);
 | 
				
			||||||
	pagefault_enable();
 | 
						pagefault_enable();
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
Efault:
 | 
					Efault:
 | 
				
			||||||
	pagefault_enable();
 | 
						pagefault_enable();
 | 
				
			||||||
	return -EFAULT;
 | 
						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)) {					\
 | 
						while (len >= sizeof(type)) {					\
 | 
				
			||||||
		__put_kernel_nofault(dst, src, type, err_label);		\
 | 
							__put_kernel_nofault(dst, src, type, err_label);		\
 | 
				
			||||||
		dst += sizeof(type);					\
 | 
							dst += sizeof(type);					\
 | 
				
			||||||
| 
						 | 
					@ -47,13 +48,13 @@ EXPORT_SYMBOL_GPL(probe_kernel_read);
 | 
				
			||||||
		len -= sizeof(type);					\
 | 
							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();
 | 
						pagefault_disable();
 | 
				
			||||||
	probe_kernel_write_loop(dst, src, size, u64, Efault);
 | 
						copy_to_kernel_nofault_loop(dst, src, size, u64, Efault);
 | 
				
			||||||
	probe_kernel_write_loop(dst, src, size, u32, Efault);
 | 
						copy_to_kernel_nofault_loop(dst, src, size, u32, Efault);
 | 
				
			||||||
	probe_kernel_write_loop(dst, src, size, u16, Efault);
 | 
						copy_to_kernel_nofault_loop(dst, src, size, u16, Efault);
 | 
				
			||||||
	probe_kernel_write_loop(dst, src, size, u8, Efault);
 | 
						copy_to_kernel_nofault_loop(dst, src, size, u8, Efault);
 | 
				
			||||||
	pagefault_enable();
 | 
						pagefault_enable();
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
Efault:
 | 
					Efault:
 | 
				
			||||||
| 
						 | 
					@ -67,7 +68,7 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (unlikely(count <= 0))
 | 
						if (unlikely(count <= 0))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	if (!probe_kernel_read_allowed(unsafe_addr, count))
 | 
						if (!copy_from_kernel_nofault_allowed(unsafe_addr, count))
 | 
				
			||||||
		return -ERANGE;
 | 
							return -ERANGE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pagefault_disable();
 | 
						pagefault_disable();
 | 
				
			||||||
| 
						 | 
					@ -87,7 +88,7 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#else /* HAVE_GET_KERNEL_NOFAULT */
 | 
					#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
 | 
					 * @dst: pointer to the buffer that shall take the data
 | 
				
			||||||
 * @src: address to read from
 | 
					 * @src: address to read from
 | 
				
			||||||
 * @size: size of the data chunk
 | 
					 * @size: size of the data chunk
 | 
				
			||||||
| 
						 | 
					@ -98,15 +99,15 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * We ensure that the copy_from_user is executed in atomic context so that
 | 
					 * 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
 | 
					 * 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.
 | 
					 * 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;
 | 
						long ret;
 | 
				
			||||||
	mm_segment_t old_fs = get_fs();
 | 
						mm_segment_t old_fs = get_fs();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!probe_kernel_read_allowed(src, size))
 | 
						if (!copy_from_kernel_nofault_allowed(src, size))
 | 
				
			||||||
		return -ERANGE;
 | 
							return -ERANGE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	set_fs(KERNEL_DS);
 | 
						set_fs(KERNEL_DS);
 | 
				
			||||||
| 
						 | 
					@ -120,10 +121,10 @@ long probe_kernel_read(void *dst, const void *src, size_t size)
 | 
				
			||||||
		return -EFAULT;
 | 
							return -EFAULT;
 | 
				
			||||||
	return 0;
 | 
						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
 | 
					 * @dst: address to write to
 | 
				
			||||||
 * @src: pointer to the data that shall be written
 | 
					 * @src: pointer to the data that shall be written
 | 
				
			||||||
 * @size: size of the data chunk
 | 
					 * @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
 | 
					 * Safely write to address @dst from the buffer at @src.  If a kernel fault
 | 
				
			||||||
 * happens, handle that and return -EFAULT.
 | 
					 * 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;
 | 
						long ret;
 | 
				
			||||||
	mm_segment_t old_fs = get_fs();
 | 
						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))
 | 
						if (unlikely(count <= 0))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	if (!probe_kernel_read_allowed(unsafe_addr, count))
 | 
						if (!copy_from_kernel_nofault_allowed(unsafe_addr, count))
 | 
				
			||||||
		return -ERANGE;
 | 
							return -ERANGE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	set_fs(KERNEL_DS);
 | 
						set_fs(KERNEL_DS);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,7 +25,7 @@ void rodata_test(void)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* test 2: write to the variable; this should fault */
 | 
						/* 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))) {
 | 
									(void *)&zero, sizeof(zero))) {
 | 
				
			||||||
		pr_err("test data was not read only\n");
 | 
							pr_err("test data was not read only\n");
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -292,7 +292,7 @@ static inline void *get_freepointer_safe(struct kmem_cache *s, void *object)
 | 
				
			||||||
		return get_freepointer(s, object);
 | 
							return get_freepointer(s, object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	freepointer_addr = (unsigned long)object + s->offset;
 | 
						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);
 | 
						return freelist_ptr(s, p, freepointer_addr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue