mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	uretprobes/x86: Hijack return address
Hijack the return address and replace it with a trampoline address. Signed-off-by: Anton Arapov <anton@redhat.com> Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Signed-off-by: Oleg Nesterov <oleg@redhat.com>
This commit is contained in:
		
							parent
							
								
									e78aebfd27
								
							
						
					
					
						commit
						791eca1010
					
				
					 2 changed files with 30 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -55,4 +55,5 @@ extern int  arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
 | 
			
		|||
extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
 | 
			
		||||
extern int  arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
 | 
			
		||||
extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
 | 
			
		||||
extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs);
 | 
			
		||||
#endif	/* _ASM_UPROBES_H */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -697,3 +697,32 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
 | 
			
		|||
		send_sig(SIGTRAP, current, 0);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned long
 | 
			
		||||
arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs)
 | 
			
		||||
{
 | 
			
		||||
	int rasize, ncopied;
 | 
			
		||||
	unsigned long orig_ret_vaddr = 0; /* clear high bits for 32-bit apps */
 | 
			
		||||
 | 
			
		||||
	rasize = is_ia32_task() ? 4 : 8;
 | 
			
		||||
	ncopied = copy_from_user(&orig_ret_vaddr, (void __user *)regs->sp, rasize);
 | 
			
		||||
	if (unlikely(ncopied))
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	/* check whether address has been already hijacked */
 | 
			
		||||
	if (orig_ret_vaddr == trampoline_vaddr)
 | 
			
		||||
		return orig_ret_vaddr;
 | 
			
		||||
 | 
			
		||||
	ncopied = copy_to_user((void __user *)regs->sp, &trampoline_vaddr, rasize);
 | 
			
		||||
	if (likely(!ncopied))
 | 
			
		||||
		return orig_ret_vaddr;
 | 
			
		||||
 | 
			
		||||
	if (ncopied != rasize) {
 | 
			
		||||
		pr_err("uprobe: return address clobbered: pid=%d, %%sp=%#lx, "
 | 
			
		||||
			"%%ip=%#lx\n", current->pid, regs->sp, regs->ip);
 | 
			
		||||
 | 
			
		||||
		force_sig_info(SIGSEGV, SEND_SIG_FORCED, current);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue