[PATCH] Return probe redesign: i386 specific changes

The following patch contains the i386 specific changes for the new
return probe design. Changes include:

* Removing the architecture specific functions for querying a return probe
instance off a stack address
* Complete rework onf arch_prepare_kretprobe() and trampoline_probe_handler()
* Removing trampoline_post_handler()
* Adding arch_init() so that now we handle registering the return probe
trampoline instead of kernel/kprobes.c doing it

Signed-off-by: Rusty Lynch <rusty.lynch@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by Rusty Lynch and committed by Linus Torvalds 4bdbd37f 802eae7c

+67 -60
+67 -60
arch/i386/kernel/kprobes.c
··· 127 127 regs->eip = (unsigned long)&p->ainsn.insn; 128 128 } 129 129 130 - struct task_struct *arch_get_kprobe_task(void *ptr) 131 - { 132 - return ((struct thread_info *) (((unsigned long) ptr) & 133 - (~(THREAD_SIZE -1))))->task; 134 - } 135 - 136 130 void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) 137 131 { 138 132 unsigned long *sara = (unsigned long *)&regs->esp; 139 - struct kretprobe_instance *ri; 140 - static void *orig_ret_addr; 133 + struct kretprobe_instance *ri; 141 134 142 - /* 143 - * Save the return address when the return probe hits 144 - * the first time, and use it to populate the (krprobe 145 - * instance)->ret_addr for subsequent return probes at 146 - * the same addrress since stack address would have 147 - * the kretprobe_trampoline by then. 148 - */ 149 - if (((void*) *sara) != kretprobe_trampoline) 150 - orig_ret_addr = (void*) *sara; 135 + if ((ri = get_free_rp_inst(rp)) != NULL) { 136 + ri->rp = rp; 137 + ri->task = current; 138 + ri->ret_addr = (kprobe_opcode_t *) *sara; 151 139 152 - if ((ri = get_free_rp_inst(rp)) != NULL) { 153 - ri->rp = rp; 154 - ri->stack_addr = sara; 155 - ri->ret_addr = orig_ret_addr; 156 - add_rp_inst(ri); 157 140 /* Replace the return addr with trampoline addr */ 158 141 *sara = (unsigned long) &kretprobe_trampoline; 159 - } else { 160 - rp->nmissed++; 161 - } 162 - } 163 142 164 - void arch_kprobe_flush_task(struct task_struct *tk) 165 - { 166 - struct kretprobe_instance *ri; 167 - while ((ri = get_rp_inst_tsk(tk)) != NULL) { 168 - *((unsigned long *)(ri->stack_addr)) = 169 - (unsigned long) ri->ret_addr; 170 - recycle_rp_inst(ri); 171 - } 143 + add_rp_inst(ri); 144 + } else { 145 + rp->nmissed++; 146 + } 172 147 } 173 148 174 149 /* ··· 261 286 */ 262 287 int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) 263 288 { 264 - struct task_struct *tsk; 265 - struct kretprobe_instance *ri; 266 - struct hlist_head *head; 267 - struct hlist_node *node; 268 - unsigned long *sara = ((unsigned long *) &regs->esp) - 1; 289 + struct kretprobe_instance *ri = NULL; 290 + struct hlist_head *head; 291 + struct hlist_node *node, *tmp; 292 + unsigned long orig_ret_address = 0; 293 + unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline; 269 294 270 - tsk = arch_get_kprobe_task(sara); 271 - head = kretprobe_inst_table_head(tsk); 295 + head = kretprobe_inst_table_head(current); 272 296 273 - hlist_for_each_entry(ri, node, head, hlist) { 274 - if (ri->stack_addr == sara && ri->rp) { 275 - if (ri->rp->handler) 276 - ri->rp->handler(ri, regs); 277 - } 278 - } 279 - return 0; 280 - } 297 + /* 298 + * It is possible to have multiple instances associated with a given 299 + * task either because an multiple functions in the call path 300 + * have a return probe installed on them, and/or more then one return 301 + * return probe was registered for a target function. 302 + * 303 + * We can handle this because: 304 + * - instances are always inserted at the head of the list 305 + * - when multiple return probes are registered for the same 306 + * function, the first instance's ret_addr will point to the 307 + * real return address, and all the rest will point to 308 + * kretprobe_trampoline 309 + */ 310 + hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { 311 + if (ri->task != current) 312 + /* another task is sharing our hash bucket */ 313 + continue; 281 314 282 - void trampoline_post_handler(struct kprobe *p, struct pt_regs *regs, 283 - unsigned long flags) 284 - { 285 - struct kretprobe_instance *ri; 286 - /* RA already popped */ 287 - unsigned long *sara = ((unsigned long *)&regs->esp) - 1; 315 + if (ri->rp && ri->rp->handler) 316 + ri->rp->handler(ri, regs); 288 317 289 - while ((ri = get_rp_inst(sara))) { 290 - regs->eip = (unsigned long)ri->ret_addr; 318 + orig_ret_address = (unsigned long)ri->ret_addr; 291 319 recycle_rp_inst(ri); 320 + 321 + if (orig_ret_address != trampoline_address) 322 + /* 323 + * This is the real return address. Any other 324 + * instances associated with this task are for 325 + * other calls deeper on the call stack 326 + */ 327 + break; 292 328 } 293 - regs->eflags &= ~TF_MASK; 329 + 330 + BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address)); 331 + regs->eip = orig_ret_address; 332 + 333 + unlock_kprobes(); 334 + preempt_enable_no_resched(); 335 + 336 + /* 337 + * By returning a non-zero value, we are telling 338 + * kprobe_handler() that we have handled unlocking 339 + * and re-enabling preemption. 340 + */ 341 + return 1; 294 342 } 295 343 296 344 /* ··· 401 403 current_kprobe->post_handler(current_kprobe, regs, 0); 402 404 } 403 405 404 - if (current_kprobe->post_handler != trampoline_post_handler) 405 - resume_execution(current_kprobe, regs); 406 + resume_execution(current_kprobe, regs); 406 407 regs->eflags |= kprobe_saved_eflags; 407 408 408 409 /*Restore back the original saved kprobes variables and continue. */ ··· 530 533 return 1; 531 534 } 532 535 return 0; 536 + } 537 + 538 + static struct kprobe trampoline_p = { 539 + .addr = (kprobe_opcode_t *) &kretprobe_trampoline, 540 + .pre_handler = trampoline_probe_handler 541 + }; 542 + 543 + int __init arch_init(void) 544 + { 545 + return register_kprobe(&trampoline_p); 533 546 }