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 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 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 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 */
 | 
					#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);
 | 
							send_sig(SIGTRAP, current, 0);
 | 
				
			||||||
	return ret;
 | 
						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