Linux Audio

Check our new training course

Yocto distribution development and maintenance

Need a Yocto distribution for your embedded project?
Loading...
v5.4
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 *  Kernel Probes Jump Optimization (Optprobes)
  4 *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  5 * Copyright (C) IBM Corporation, 2002, 2004
  6 * Copyright (C) Hitachi Ltd., 2012
  7 */
  8#include <linux/kprobes.h>
  9#include <linux/ptrace.h>
 10#include <linux/string.h>
 11#include <linux/slab.h>
 12#include <linux/hardirq.h>
 13#include <linux/preempt.h>
 14#include <linux/extable.h>
 15#include <linux/kdebug.h>
 16#include <linux/kallsyms.h>
 17#include <linux/ftrace.h>
 18#include <linux/frame.h>
 19
 20#include <asm/text-patching.h>
 21#include <asm/cacheflush.h>
 22#include <asm/desc.h>
 23#include <asm/pgtable.h>
 24#include <linux/uaccess.h>
 25#include <asm/alternative.h>
 26#include <asm/insn.h>
 27#include <asm/debugreg.h>
 28#include <asm/set_memory.h>
 29#include <asm/sections.h>
 30#include <asm/nospec-branch.h>
 31
 32#include "common.h"
 33
 34unsigned long __recover_optprobed_insn(kprobe_opcode_t *buf, unsigned long addr)
 35{
 36	struct optimized_kprobe *op;
 37	struct kprobe *kp;
 38	long offs;
 39	int i;
 40
 41	for (i = 0; i < RELATIVEJUMP_SIZE; i++) {
 42		kp = get_kprobe((void *)addr - i);
 43		/* This function only handles jump-optimized kprobe */
 44		if (kp && kprobe_optimized(kp)) {
 45			op = container_of(kp, struct optimized_kprobe, kp);
 46			/* If op->list is not empty, op is under optimizing */
 47			if (list_empty(&op->list))
 48				goto found;
 49		}
 50	}
 51
 52	return addr;
 53found:
 54	/*
 55	 * If the kprobe can be optimized, original bytes which can be
 56	 * overwritten by jump destination address. In this case, original
 57	 * bytes must be recovered from op->optinsn.copied_insn buffer.
 58	 */
 59	if (probe_kernel_read(buf, (void *)addr,
 60		MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
 61		return 0UL;
 62
 63	if (addr == (unsigned long)kp->addr) {
 64		buf[0] = kp->opcode;
 65		memcpy(buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
 66	} else {
 67		offs = addr - (unsigned long)kp->addr - 1;
 68		memcpy(buf, op->optinsn.copied_insn + offs, RELATIVE_ADDR_SIZE - offs);
 69	}
 70
 71	return (unsigned long)buf;
 72}
 73
 74/* Insert a move instruction which sets a pointer to eax/rdi (1st arg). */
 75static void synthesize_set_arg1(kprobe_opcode_t *addr, unsigned long val)
 76{
 77#ifdef CONFIG_X86_64
 78	*addr++ = 0x48;
 79	*addr++ = 0xbf;
 80#else
 81	*addr++ = 0xb8;
 82#endif
 83	*(unsigned long *)addr = val;
 84}
 85
 86asm (
 87			".pushsection .rodata\n"
 88			"optprobe_template_func:\n"
 89			".global optprobe_template_entry\n"
 90			"optprobe_template_entry:\n"
 91#ifdef CONFIG_X86_64
 92			/* We don't bother saving the ss register */
 93			"	pushq %rsp\n"
 94			"	pushfq\n"
 95			SAVE_REGS_STRING
 96			"	movq %rsp, %rsi\n"
 97			".global optprobe_template_val\n"
 98			"optprobe_template_val:\n"
 99			ASM_NOP5
100			ASM_NOP5
101			".global optprobe_template_call\n"
102			"optprobe_template_call:\n"
103			ASM_NOP5
104			/* Move flags to rsp */
105			"	movq 18*8(%rsp), %rdx\n"
106			"	movq %rdx, 19*8(%rsp)\n"
107			RESTORE_REGS_STRING
108			/* Skip flags entry */
109			"	addq $8, %rsp\n"
110			"	popfq\n"
111#else /* CONFIG_X86_32 */
112			"	pushl %esp\n"
113			"	pushfl\n"
114			SAVE_REGS_STRING
115			"	movl %esp, %edx\n"
116			".global optprobe_template_val\n"
117			"optprobe_template_val:\n"
118			ASM_NOP5
119			".global optprobe_template_call\n"
120			"optprobe_template_call:\n"
121			ASM_NOP5
122			/* Move flags into esp */
123			"	movl 14*4(%esp), %edx\n"
124			"	movl %edx, 15*4(%esp)\n"
125			RESTORE_REGS_STRING
126			/* Skip flags entry */
127			"	addl $4, %esp\n"
128			"	popfl\n"
129#endif
130			".global optprobe_template_end\n"
131			"optprobe_template_end:\n"
132			".popsection\n");
133
134void optprobe_template_func(void);
135STACK_FRAME_NON_STANDARD(optprobe_template_func);
136
137#define TMPL_MOVE_IDX \
138	((long)optprobe_template_val - (long)optprobe_template_entry)
139#define TMPL_CALL_IDX \
140	((long)optprobe_template_call - (long)optprobe_template_entry)
141#define TMPL_END_IDX \
142	((long)optprobe_template_end - (long)optprobe_template_entry)
143
144#define INT3_SIZE sizeof(kprobe_opcode_t)
145
146/* Optimized kprobe call back function: called from optinsn */
147static void
148optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs)
149{
 
 
 
150	/* This is possible if op is under delayed unoptimizing */
151	if (kprobe_disabled(&op->kp))
152		return;
153
154	preempt_disable();
155	if (kprobe_running()) {
156		kprobes_inc_nmissed_count(&op->kp);
157	} else {
158		struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
159		/* Save skipped registers */
 
160		regs->cs = __KERNEL_CS;
161#ifdef CONFIG_X86_32
162		regs->cs |= get_kernel_rpl();
163		regs->gs = 0;
164#endif
165		regs->ip = (unsigned long)op->kp.addr + INT3_SIZE;
166		regs->orig_ax = ~0UL;
167
168		__this_cpu_write(current_kprobe, &op->kp);
169		kcb->kprobe_status = KPROBE_HIT_ACTIVE;
170		opt_pre_handler(&op->kp, regs);
171		__this_cpu_write(current_kprobe, NULL);
172	}
173	preempt_enable();
174}
175NOKPROBE_SYMBOL(optimized_callback);
176
177static int copy_optimized_instructions(u8 *dest, u8 *src, u8 *real)
178{
179	struct insn insn;
180	int len = 0, ret;
181
182	while (len < RELATIVEJUMP_SIZE) {
183		ret = __copy_instruction(dest + len, src + len, real + len, &insn);
184		if (!ret || !can_boost(&insn, src + len))
185			return -EINVAL;
186		len += ret;
187	}
188	/* Check whether the address range is reserved */
189	if (ftrace_text_reserved(src, src + len - 1) ||
190	    alternatives_text_reserved(src, src + len - 1) ||
191	    jump_label_text_reserved(src, src + len - 1))
192		return -EBUSY;
193
194	return len;
195}
196
197/* Check whether insn is indirect jump */
198static int __insn_is_indirect_jump(struct insn *insn)
199{
200	return ((insn->opcode.bytes[0] == 0xff &&
201		(X86_MODRM_REG(insn->modrm.value) & 6) == 4) || /* Jump */
202		insn->opcode.bytes[0] == 0xea);	/* Segment based jump */
203}
204
205/* Check whether insn jumps into specified address range */
206static int insn_jump_into_range(struct insn *insn, unsigned long start, int len)
207{
208	unsigned long target = 0;
209
210	switch (insn->opcode.bytes[0]) {
211	case 0xe0:	/* loopne */
212	case 0xe1:	/* loope */
213	case 0xe2:	/* loop */
214	case 0xe3:	/* jcxz */
215	case 0xe9:	/* near relative jump */
216	case 0xeb:	/* short relative jump */
217		break;
218	case 0x0f:
219		if ((insn->opcode.bytes[1] & 0xf0) == 0x80) /* jcc near */
220			break;
221		return 0;
222	default:
223		if ((insn->opcode.bytes[0] & 0xf0) == 0x70) /* jcc short */
224			break;
225		return 0;
226	}
227	target = (unsigned long)insn->next_byte + insn->immediate.value;
228
229	return (start <= target && target <= start + len);
230}
231
232static int insn_is_indirect_jump(struct insn *insn)
233{
234	int ret = __insn_is_indirect_jump(insn);
235
236#ifdef CONFIG_RETPOLINE
237	/*
238	 * Jump to x86_indirect_thunk_* is treated as an indirect jump.
239	 * Note that even with CONFIG_RETPOLINE=y, the kernel compiled with
240	 * older gcc may use indirect jump. So we add this check instead of
241	 * replace indirect-jump check.
242	 */
243	if (!ret)
244		ret = insn_jump_into_range(insn,
245				(unsigned long)__indirect_thunk_start,
246				(unsigned long)__indirect_thunk_end -
247				(unsigned long)__indirect_thunk_start);
248#endif
249	return ret;
250}
251
252/* Decode whole function to ensure any instructions don't jump into target */
253static int can_optimize(unsigned long paddr)
254{
255	unsigned long addr, size = 0, offset = 0;
256	struct insn insn;
257	kprobe_opcode_t buf[MAX_INSN_SIZE];
258
259	/* Lookup symbol including addr */
260	if (!kallsyms_lookup_size_offset(paddr, &size, &offset))
261		return 0;
262
263	/*
264	 * Do not optimize in the entry code due to the unstable
265	 * stack handling and registers setup.
266	 */
267	if (((paddr >= (unsigned long)__entry_text_start) &&
268	     (paddr <  (unsigned long)__entry_text_end)) ||
269	    ((paddr >= (unsigned long)__irqentry_text_start) &&
270	     (paddr <  (unsigned long)__irqentry_text_end)))
271		return 0;
272
273	/* Check there is enough space for a relative jump. */
274	if (size - offset < RELATIVEJUMP_SIZE)
275		return 0;
276
277	/* Decode instructions */
278	addr = paddr - offset;
279	while (addr < paddr - offset + size) { /* Decode until function end */
280		unsigned long recovered_insn;
281		if (search_exception_tables(addr))
282			/*
283			 * Since some fixup code will jumps into this function,
284			 * we can't optimize kprobe in this function.
285			 */
286			return 0;
287		recovered_insn = recover_probed_instruction(buf, addr);
288		if (!recovered_insn)
289			return 0;
290		kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE);
291		insn_get_length(&insn);
292		/* Another subsystem puts a breakpoint */
293		if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION)
294			return 0;
295		/* Recover address */
296		insn.kaddr = (void *)addr;
297		insn.next_byte = (void *)(addr + insn.length);
298		/* Check any instructions don't jump into target */
299		if (insn_is_indirect_jump(&insn) ||
300		    insn_jump_into_range(&insn, paddr + INT3_SIZE,
301					 RELATIVE_ADDR_SIZE))
302			return 0;
303		addr += insn.length;
304	}
305
306	return 1;
307}
308
309/* Check optimized_kprobe can actually be optimized. */
310int arch_check_optimized_kprobe(struct optimized_kprobe *op)
311{
312	int i;
313	struct kprobe *p;
314
315	for (i = 1; i < op->optinsn.size; i++) {
316		p = get_kprobe(op->kp.addr + i);
317		if (p && !kprobe_disabled(p))
318			return -EEXIST;
319	}
320
321	return 0;
322}
323
324/* Check the addr is within the optimized instructions. */
325int arch_within_optimized_kprobe(struct optimized_kprobe *op,
326				 unsigned long addr)
327{
328	return ((unsigned long)op->kp.addr <= addr &&
329		(unsigned long)op->kp.addr + op->optinsn.size > addr);
330}
331
332/* Free optimized instruction slot */
333static
334void __arch_remove_optimized_kprobe(struct optimized_kprobe *op, int dirty)
335{
336	if (op->optinsn.insn) {
337		free_optinsn_slot(op->optinsn.insn, dirty);
338		op->optinsn.insn = NULL;
339		op->optinsn.size = 0;
340	}
341}
342
343void arch_remove_optimized_kprobe(struct optimized_kprobe *op)
344{
345	__arch_remove_optimized_kprobe(op, 1);
346}
347
348/*
349 * Copy replacing target instructions
350 * Target instructions MUST be relocatable (checked inside)
351 * This is called when new aggr(opt)probe is allocated or reused.
352 */
353int arch_prepare_optimized_kprobe(struct optimized_kprobe *op,
354				  struct kprobe *__unused)
355{
356	u8 *buf = NULL, *slot;
357	int ret, len;
358	long rel;
359
360	if (!can_optimize((unsigned long)op->kp.addr))
361		return -EILSEQ;
362
363	buf = kzalloc(MAX_OPTINSN_SIZE, GFP_KERNEL);
364	if (!buf)
365		return -ENOMEM;
366
367	op->optinsn.insn = slot = get_optinsn_slot();
368	if (!slot) {
369		ret = -ENOMEM;
370		goto out;
371	}
372
373	/*
374	 * Verify if the address gap is in 2GB range, because this uses
375	 * a relative jump.
376	 */
377	rel = (long)slot - (long)op->kp.addr + RELATIVEJUMP_SIZE;
378	if (abs(rel) > 0x7fffffff) {
379		ret = -ERANGE;
380		goto err;
381	}
382
383	/* Copy arch-dep-instance from template */
384	memcpy(buf, optprobe_template_entry, TMPL_END_IDX);
385
386	/* Copy instructions into the out-of-line buffer */
387	ret = copy_optimized_instructions(buf + TMPL_END_IDX, op->kp.addr,
388					  slot + TMPL_END_IDX);
389	if (ret < 0)
390		goto err;
 
391	op->optinsn.size = ret;
392	len = TMPL_END_IDX + op->optinsn.size;
 
 
393
394	/* Set probe information */
395	synthesize_set_arg1(buf + TMPL_MOVE_IDX, (unsigned long)op);
396
397	/* Set probe function call */
398	synthesize_relcall(buf + TMPL_CALL_IDX,
399			   slot + TMPL_CALL_IDX, optimized_callback);
400
401	/* Set returning jmp instruction at the tail of out-of-line buffer */
402	synthesize_reljump(buf + len, slot + len,
403			   (u8 *)op->kp.addr + op->optinsn.size);
404	len += RELATIVEJUMP_SIZE;
405
406	/* We have to use text_poke() for instruction buffer because it is RO */
407	text_poke(slot, buf, len);
408	ret = 0;
409out:
410	kfree(buf);
411	return ret;
412
413err:
414	__arch_remove_optimized_kprobe(op, 0);
415	goto out;
416}
417
418/*
419 * Replace breakpoints (int3) with relative jumps.
420 * Caller must call with locking kprobe_mutex and text_mutex.
421 */
422void arch_optimize_kprobes(struct list_head *oplist)
423{
424	struct optimized_kprobe *op, *tmp;
425	u8 insn_buff[RELATIVEJUMP_SIZE];
426
427	list_for_each_entry_safe(op, tmp, oplist, list) {
428		s32 rel = (s32)((long)op->optinsn.insn -
429			((long)op->kp.addr + RELATIVEJUMP_SIZE));
430
431		WARN_ON(kprobe_disabled(&op->kp));
432
433		/* Backup instructions which will be replaced by jump address */
434		memcpy(op->optinsn.copied_insn, op->kp.addr + INT3_SIZE,
435		       RELATIVE_ADDR_SIZE);
436
437		insn_buff[0] = RELATIVEJUMP_OPCODE;
438		*(s32 *)(&insn_buff[1]) = rel;
439
440		text_poke_bp(op->kp.addr, insn_buff, RELATIVEJUMP_SIZE,
441			     op->optinsn.insn);
442
443		list_del_init(&op->list);
444	}
445}
446
447/* Replace a relative jump with a breakpoint (int3).  */
448void arch_unoptimize_kprobe(struct optimized_kprobe *op)
449{
450	u8 insn_buff[RELATIVEJUMP_SIZE];
451
452	/* Set int3 to first byte for kprobes */
453	insn_buff[0] = BREAKPOINT_INSTRUCTION;
454	memcpy(insn_buff + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
455	text_poke_bp(op->kp.addr, insn_buff, RELATIVEJUMP_SIZE,
456		     op->optinsn.insn);
457}
458
459/*
460 * Recover original instructions and breakpoints from relative jumps.
461 * Caller must call with locking kprobe_mutex.
462 */
463extern void arch_unoptimize_kprobes(struct list_head *oplist,
464				    struct list_head *done_list)
465{
466	struct optimized_kprobe *op, *tmp;
467
468	list_for_each_entry_safe(op, tmp, oplist, list) {
469		arch_unoptimize_kprobe(op);
470		list_move(&op->list, done_list);
471	}
472}
473
474int setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter)
475{
476	struct optimized_kprobe *op;
477
478	if (p->flags & KPROBE_FLAG_OPTIMIZED) {
479		/* This kprobe is really able to run optimized path. */
480		op = container_of(p, struct optimized_kprobe, kp);
481		/* Detour through copied instructions */
482		regs->ip = (unsigned long)op->optinsn.insn + TMPL_END_IDX;
483		if (!reenter)
484			reset_current_kprobe();
 
485		return 1;
486	}
487	return 0;
488}
489NOKPROBE_SYMBOL(setup_detour_execution);
v4.6
 
  1/*
  2 *  Kernel Probes Jump Optimization (Optprobes)
  3 *
  4 * This program is free software; you can redistribute it and/or modify
  5 * it under the terms of the GNU General Public License as published by
  6 * the Free Software Foundation; either version 2 of the License, or
  7 * (at your option) any later version.
  8 *
  9 * This program is distributed in the hope that it will be useful,
 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12 * GNU General Public License for more details.
 13 *
 14 * You should have received a copy of the GNU General Public License
 15 * along with this program; if not, write to the Free Software
 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 17 *
 18 * Copyright (C) IBM Corporation, 2002, 2004
 19 * Copyright (C) Hitachi Ltd., 2012
 20 */
 21#include <linux/kprobes.h>
 22#include <linux/ptrace.h>
 23#include <linux/string.h>
 24#include <linux/slab.h>
 25#include <linux/hardirq.h>
 26#include <linux/preempt.h>
 27#include <linux/module.h>
 28#include <linux/kdebug.h>
 29#include <linux/kallsyms.h>
 30#include <linux/ftrace.h>
 
 31
 
 32#include <asm/cacheflush.h>
 33#include <asm/desc.h>
 34#include <asm/pgtable.h>
 35#include <asm/uaccess.h>
 36#include <asm/alternative.h>
 37#include <asm/insn.h>
 38#include <asm/debugreg.h>
 
 
 
 39
 40#include "common.h"
 41
 42unsigned long __recover_optprobed_insn(kprobe_opcode_t *buf, unsigned long addr)
 43{
 44	struct optimized_kprobe *op;
 45	struct kprobe *kp;
 46	long offs;
 47	int i;
 48
 49	for (i = 0; i < RELATIVEJUMP_SIZE; i++) {
 50		kp = get_kprobe((void *)addr - i);
 51		/* This function only handles jump-optimized kprobe */
 52		if (kp && kprobe_optimized(kp)) {
 53			op = container_of(kp, struct optimized_kprobe, kp);
 54			/* If op->list is not empty, op is under optimizing */
 55			if (list_empty(&op->list))
 56				goto found;
 57		}
 58	}
 59
 60	return addr;
 61found:
 62	/*
 63	 * If the kprobe can be optimized, original bytes which can be
 64	 * overwritten by jump destination address. In this case, original
 65	 * bytes must be recovered from op->optinsn.copied_insn buffer.
 66	 */
 67	memcpy(buf, (void *)addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
 
 
 
 68	if (addr == (unsigned long)kp->addr) {
 69		buf[0] = kp->opcode;
 70		memcpy(buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
 71	} else {
 72		offs = addr - (unsigned long)kp->addr - 1;
 73		memcpy(buf, op->optinsn.copied_insn + offs, RELATIVE_ADDR_SIZE - offs);
 74	}
 75
 76	return (unsigned long)buf;
 77}
 78
 79/* Insert a move instruction which sets a pointer to eax/rdi (1st arg). */
 80static void synthesize_set_arg1(kprobe_opcode_t *addr, unsigned long val)
 81{
 82#ifdef CONFIG_X86_64
 83	*addr++ = 0x48;
 84	*addr++ = 0xbf;
 85#else
 86	*addr++ = 0xb8;
 87#endif
 88	*(unsigned long *)addr = val;
 89}
 90
 91asm (
 
 
 92			".global optprobe_template_entry\n"
 93			"optprobe_template_entry:\n"
 94#ifdef CONFIG_X86_64
 95			/* We don't bother saving the ss register */
 96			"	pushq %rsp\n"
 97			"	pushfq\n"
 98			SAVE_REGS_STRING
 99			"	movq %rsp, %rsi\n"
100			".global optprobe_template_val\n"
101			"optprobe_template_val:\n"
102			ASM_NOP5
103			ASM_NOP5
104			".global optprobe_template_call\n"
105			"optprobe_template_call:\n"
106			ASM_NOP5
107			/* Move flags to rsp */
108			"	movq 144(%rsp), %rdx\n"
109			"	movq %rdx, 152(%rsp)\n"
110			RESTORE_REGS_STRING
111			/* Skip flags entry */
112			"	addq $8, %rsp\n"
113			"	popfq\n"
114#else /* CONFIG_X86_32 */
115			"	pushf\n"
 
116			SAVE_REGS_STRING
117			"	movl %esp, %edx\n"
118			".global optprobe_template_val\n"
119			"optprobe_template_val:\n"
120			ASM_NOP5
121			".global optprobe_template_call\n"
122			"optprobe_template_call:\n"
123			ASM_NOP5
 
 
 
124			RESTORE_REGS_STRING
125			"	addl $4, %esp\n"	/* skip cs */
126			"	popf\n"
 
127#endif
128			".global optprobe_template_end\n"
129			"optprobe_template_end:\n");
 
 
 
 
130
131#define TMPL_MOVE_IDX \
132	((long)&optprobe_template_val - (long)&optprobe_template_entry)
133#define TMPL_CALL_IDX \
134	((long)&optprobe_template_call - (long)&optprobe_template_entry)
135#define TMPL_END_IDX \
136	((long)&optprobe_template_end - (long)&optprobe_template_entry)
137
138#define INT3_SIZE sizeof(kprobe_opcode_t)
139
140/* Optimized kprobe call back function: called from optinsn */
141static void
142optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs)
143{
144	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
145	unsigned long flags;
146
147	/* This is possible if op is under delayed unoptimizing */
148	if (kprobe_disabled(&op->kp))
149		return;
150
151	local_irq_save(flags);
152	if (kprobe_running()) {
153		kprobes_inc_nmissed_count(&op->kp);
154	} else {
 
155		/* Save skipped registers */
156#ifdef CONFIG_X86_64
157		regs->cs = __KERNEL_CS;
158#else
159		regs->cs = __KERNEL_CS | get_kernel_rpl();
160		regs->gs = 0;
161#endif
162		regs->ip = (unsigned long)op->kp.addr + INT3_SIZE;
163		regs->orig_ax = ~0UL;
164
165		__this_cpu_write(current_kprobe, &op->kp);
166		kcb->kprobe_status = KPROBE_HIT_ACTIVE;
167		opt_pre_handler(&op->kp, regs);
168		__this_cpu_write(current_kprobe, NULL);
169	}
170	local_irq_restore(flags);
171}
172NOKPROBE_SYMBOL(optimized_callback);
173
174static int copy_optimized_instructions(u8 *dest, u8 *src)
175{
 
176	int len = 0, ret;
177
178	while (len < RELATIVEJUMP_SIZE) {
179		ret = __copy_instruction(dest + len, src + len);
180		if (!ret || !can_boost(dest + len))
181			return -EINVAL;
182		len += ret;
183	}
184	/* Check whether the address range is reserved */
185	if (ftrace_text_reserved(src, src + len - 1) ||
186	    alternatives_text_reserved(src, src + len - 1) ||
187	    jump_label_text_reserved(src, src + len - 1))
188		return -EBUSY;
189
190	return len;
191}
192
193/* Check whether insn is indirect jump */
194static int insn_is_indirect_jump(struct insn *insn)
195{
196	return ((insn->opcode.bytes[0] == 0xff &&
197		(X86_MODRM_REG(insn->modrm.value) & 6) == 4) || /* Jump */
198		insn->opcode.bytes[0] == 0xea);	/* Segment based jump */
199}
200
201/* Check whether insn jumps into specified address range */
202static int insn_jump_into_range(struct insn *insn, unsigned long start, int len)
203{
204	unsigned long target = 0;
205
206	switch (insn->opcode.bytes[0]) {
207	case 0xe0:	/* loopne */
208	case 0xe1:	/* loope */
209	case 0xe2:	/* loop */
210	case 0xe3:	/* jcxz */
211	case 0xe9:	/* near relative jump */
212	case 0xeb:	/* short relative jump */
213		break;
214	case 0x0f:
215		if ((insn->opcode.bytes[1] & 0xf0) == 0x80) /* jcc near */
216			break;
217		return 0;
218	default:
219		if ((insn->opcode.bytes[0] & 0xf0) == 0x70) /* jcc short */
220			break;
221		return 0;
222	}
223	target = (unsigned long)insn->next_byte + insn->immediate.value;
224
225	return (start <= target && target <= start + len);
226}
227
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228/* Decode whole function to ensure any instructions don't jump into target */
229static int can_optimize(unsigned long paddr)
230{
231	unsigned long addr, size = 0, offset = 0;
232	struct insn insn;
233	kprobe_opcode_t buf[MAX_INSN_SIZE];
234
235	/* Lookup symbol including addr */
236	if (!kallsyms_lookup_size_offset(paddr, &size, &offset))
237		return 0;
238
239	/*
240	 * Do not optimize in the entry code due to the unstable
241	 * stack handling.
242	 */
243	if ((paddr >= (unsigned long)__entry_text_start) &&
244	    (paddr <  (unsigned long)__entry_text_end))
 
 
245		return 0;
246
247	/* Check there is enough space for a relative jump. */
248	if (size - offset < RELATIVEJUMP_SIZE)
249		return 0;
250
251	/* Decode instructions */
252	addr = paddr - offset;
253	while (addr < paddr - offset + size) { /* Decode until function end */
254		unsigned long recovered_insn;
255		if (search_exception_tables(addr))
256			/*
257			 * Since some fixup code will jumps into this function,
258			 * we can't optimize kprobe in this function.
259			 */
260			return 0;
261		recovered_insn = recover_probed_instruction(buf, addr);
262		if (!recovered_insn)
263			return 0;
264		kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE);
265		insn_get_length(&insn);
266		/* Another subsystem puts a breakpoint */
267		if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION)
268			return 0;
269		/* Recover address */
270		insn.kaddr = (void *)addr;
271		insn.next_byte = (void *)(addr + insn.length);
272		/* Check any instructions don't jump into target */
273		if (insn_is_indirect_jump(&insn) ||
274		    insn_jump_into_range(&insn, paddr + INT3_SIZE,
275					 RELATIVE_ADDR_SIZE))
276			return 0;
277		addr += insn.length;
278	}
279
280	return 1;
281}
282
283/* Check optimized_kprobe can actually be optimized. */
284int arch_check_optimized_kprobe(struct optimized_kprobe *op)
285{
286	int i;
287	struct kprobe *p;
288
289	for (i = 1; i < op->optinsn.size; i++) {
290		p = get_kprobe(op->kp.addr + i);
291		if (p && !kprobe_disabled(p))
292			return -EEXIST;
293	}
294
295	return 0;
296}
297
298/* Check the addr is within the optimized instructions. */
299int arch_within_optimized_kprobe(struct optimized_kprobe *op,
300				 unsigned long addr)
301{
302	return ((unsigned long)op->kp.addr <= addr &&
303		(unsigned long)op->kp.addr + op->optinsn.size > addr);
304}
305
306/* Free optimized instruction slot */
307static
308void __arch_remove_optimized_kprobe(struct optimized_kprobe *op, int dirty)
309{
310	if (op->optinsn.insn) {
311		free_optinsn_slot(op->optinsn.insn, dirty);
312		op->optinsn.insn = NULL;
313		op->optinsn.size = 0;
314	}
315}
316
317void arch_remove_optimized_kprobe(struct optimized_kprobe *op)
318{
319	__arch_remove_optimized_kprobe(op, 1);
320}
321
322/*
323 * Copy replacing target instructions
324 * Target instructions MUST be relocatable (checked inside)
325 * This is called when new aggr(opt)probe is allocated or reused.
326 */
327int arch_prepare_optimized_kprobe(struct optimized_kprobe *op,
328				  struct kprobe *__unused)
329{
330	u8 *buf;
331	int ret;
332	long rel;
333
334	if (!can_optimize((unsigned long)op->kp.addr))
335		return -EILSEQ;
336
337	op->optinsn.insn = get_optinsn_slot();
338	if (!op->optinsn.insn)
339		return -ENOMEM;
340
 
 
 
 
 
 
341	/*
342	 * Verify if the address gap is in 2GB range, because this uses
343	 * a relative jump.
344	 */
345	rel = (long)op->optinsn.insn - (long)op->kp.addr + RELATIVEJUMP_SIZE;
346	if (abs(rel) > 0x7fffffff) {
347		__arch_remove_optimized_kprobe(op, 0);
348		return -ERANGE;
349	}
350
351	buf = (u8 *)op->optinsn.insn;
 
352
353	/* Copy instructions into the out-of-line buffer */
354	ret = copy_optimized_instructions(buf + TMPL_END_IDX, op->kp.addr);
355	if (ret < 0) {
356		__arch_remove_optimized_kprobe(op, 0);
357		return ret;
358	}
359	op->optinsn.size = ret;
360
361	/* Copy arch-dep-instance from template */
362	memcpy(buf, &optprobe_template_entry, TMPL_END_IDX);
363
364	/* Set probe information */
365	synthesize_set_arg1(buf + TMPL_MOVE_IDX, (unsigned long)op);
366
367	/* Set probe function call */
368	synthesize_relcall(buf + TMPL_CALL_IDX, optimized_callback);
 
369
370	/* Set returning jmp instruction at the tail of out-of-line buffer */
371	synthesize_reljump(buf + TMPL_END_IDX + op->optinsn.size,
372			   (u8 *)op->kp.addr + op->optinsn.size);
 
373
374	flush_icache_range((unsigned long) buf,
375			   (unsigned long) buf + TMPL_END_IDX +
376			   op->optinsn.size + RELATIVEJUMP_SIZE);
377	return 0;
 
 
 
 
 
 
378}
379
380/*
381 * Replace breakpoints (int3) with relative jumps.
382 * Caller must call with locking kprobe_mutex and text_mutex.
383 */
384void arch_optimize_kprobes(struct list_head *oplist)
385{
386	struct optimized_kprobe *op, *tmp;
387	u8 insn_buf[RELATIVEJUMP_SIZE];
388
389	list_for_each_entry_safe(op, tmp, oplist, list) {
390		s32 rel = (s32)((long)op->optinsn.insn -
391			((long)op->kp.addr + RELATIVEJUMP_SIZE));
392
393		WARN_ON(kprobe_disabled(&op->kp));
394
395		/* Backup instructions which will be replaced by jump address */
396		memcpy(op->optinsn.copied_insn, op->kp.addr + INT3_SIZE,
397		       RELATIVE_ADDR_SIZE);
398
399		insn_buf[0] = RELATIVEJUMP_OPCODE;
400		*(s32 *)(&insn_buf[1]) = rel;
401
402		text_poke_bp(op->kp.addr, insn_buf, RELATIVEJUMP_SIZE,
403			     op->optinsn.insn);
404
405		list_del_init(&op->list);
406	}
407}
408
409/* Replace a relative jump with a breakpoint (int3).  */
410void arch_unoptimize_kprobe(struct optimized_kprobe *op)
411{
412	u8 insn_buf[RELATIVEJUMP_SIZE];
413
414	/* Set int3 to first byte for kprobes */
415	insn_buf[0] = BREAKPOINT_INSTRUCTION;
416	memcpy(insn_buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
417	text_poke_bp(op->kp.addr, insn_buf, RELATIVEJUMP_SIZE,
418		     op->optinsn.insn);
419}
420
421/*
422 * Recover original instructions and breakpoints from relative jumps.
423 * Caller must call with locking kprobe_mutex.
424 */
425extern void arch_unoptimize_kprobes(struct list_head *oplist,
426				    struct list_head *done_list)
427{
428	struct optimized_kprobe *op, *tmp;
429
430	list_for_each_entry_safe(op, tmp, oplist, list) {
431		arch_unoptimize_kprobe(op);
432		list_move(&op->list, done_list);
433	}
434}
435
436int setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter)
437{
438	struct optimized_kprobe *op;
439
440	if (p->flags & KPROBE_FLAG_OPTIMIZED) {
441		/* This kprobe is really able to run optimized path. */
442		op = container_of(p, struct optimized_kprobe, kp);
443		/* Detour through copied instructions */
444		regs->ip = (unsigned long)op->optinsn.insn + TMPL_END_IDX;
445		if (!reenter)
446			reset_current_kprobe();
447		preempt_enable_no_resched();
448		return 1;
449	}
450	return 0;
451}
452NOKPROBE_SYMBOL(setup_detour_execution);