mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	x86/kprobes: Cleanup kprobes on ftrace code
Cleanup kprobes on ftrace code for x86. - Set instruction pointer (ip + MCOUNT_INSN_SIZE) after pre_handler only when p->post_handler exists. - Use INT3_INSN_SIZE instead of 1. - Use instruction_pointer/instruction_pointer_set() functions instead of accessing regs->ip directly. Link: https://lore.kernel.org/all/172951436219.167263.18330240454389154327.stgit@devnote2/ Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
This commit is contained in:
		
							parent
							
								
									3fbff98889
								
							
						
					
					
						commit
						4638d7ebef
					
				
					 1 changed files with 11 additions and 8 deletions
				
			
		| 
						 | 
				
			
			@ -9,6 +9,7 @@
 | 
			
		|||
#include <linux/hardirq.h>
 | 
			
		||||
#include <linux/preempt.h>
 | 
			
		||||
#include <linux/ftrace.h>
 | 
			
		||||
#include <asm/text-patching.h>
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -36,23 +37,25 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
 | 
			
		|||
	if (kprobe_running()) {
 | 
			
		||||
		kprobes_inc_nmissed_count(p);
 | 
			
		||||
	} else {
 | 
			
		||||
		unsigned long orig_ip = regs->ip;
 | 
			
		||||
		unsigned long orig_ip = instruction_pointer(regs);
 | 
			
		||||
 | 
			
		||||
		/* Kprobe handler expects regs->ip = ip + 1 as breakpoint hit */
 | 
			
		||||
		regs->ip = ip + sizeof(kprobe_opcode_t);
 | 
			
		||||
		instruction_pointer_set(regs, ip + INT3_INSN_SIZE);
 | 
			
		||||
 | 
			
		||||
		__this_cpu_write(current_kprobe, p);
 | 
			
		||||
		kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 | 
			
		||||
		if (!p->pre_handler || !p->pre_handler(p, regs)) {
 | 
			
		||||
			if (unlikely(p->post_handler)) {
 | 
			
		||||
				/*
 | 
			
		||||
				 * Emulate singlestep (and also recover regs->ip)
 | 
			
		||||
				 * as if there is a 5byte nop
 | 
			
		||||
				 */
 | 
			
		||||
			regs->ip = (unsigned long)p->addr + MCOUNT_INSN_SIZE;
 | 
			
		||||
			if (unlikely(p->post_handler)) {
 | 
			
		||||
				instruction_pointer_set(regs, ip + MCOUNT_INSN_SIZE);
 | 
			
		||||
				kcb->kprobe_status = KPROBE_HIT_SSDONE;
 | 
			
		||||
				p->post_handler(p, regs, 0);
 | 
			
		||||
			}
 | 
			
		||||
			regs->ip = orig_ip;
 | 
			
		||||
			/* Recover IP address */
 | 
			
		||||
			instruction_pointer_set(regs, orig_ip);
 | 
			
		||||
		}
 | 
			
		||||
		/*
 | 
			
		||||
		 * If pre_handler returns !0, it changes regs->ip. We have to
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue