diff options
Diffstat (limited to 'kernel/kprobes.c')
| -rw-r--r-- | kernel/kprobes.c | 94 |
1 files changed, 65 insertions, 29 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index b0237122b24e..f3ea492ab44d 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
| 38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
| 39 | #include <linux/moduleloader.h> | 39 | #include <linux/moduleloader.h> |
| 40 | #include <asm-generic/sections.h> | ||
| 40 | #include <asm/cacheflush.h> | 41 | #include <asm/cacheflush.h> |
| 41 | #include <asm/errno.h> | 42 | #include <asm/errno.h> |
| 42 | #include <asm/kdebug.h> | 43 | #include <asm/kdebug.h> |
| @@ -72,7 +73,7 @@ static struct hlist_head kprobe_insn_pages; | |||
| 72 | * get_insn_slot() - Find a slot on an executable page for an instruction. | 73 | * get_insn_slot() - Find a slot on an executable page for an instruction. |
| 73 | * We allocate an executable page if there's no room on existing ones. | 74 | * We allocate an executable page if there's no room on existing ones. |
| 74 | */ | 75 | */ |
| 75 | kprobe_opcode_t *get_insn_slot(void) | 76 | kprobe_opcode_t __kprobes *get_insn_slot(void) |
| 76 | { | 77 | { |
| 77 | struct kprobe_insn_page *kip; | 78 | struct kprobe_insn_page *kip; |
| 78 | struct hlist_node *pos; | 79 | struct hlist_node *pos; |
| @@ -117,7 +118,7 @@ kprobe_opcode_t *get_insn_slot(void) | |||
| 117 | return kip->insns; | 118 | return kip->insns; |
| 118 | } | 119 | } |
| 119 | 120 | ||
| 120 | void free_insn_slot(kprobe_opcode_t *slot) | 121 | void __kprobes free_insn_slot(kprobe_opcode_t *slot) |
| 121 | { | 122 | { |
| 122 | struct kprobe_insn_page *kip; | 123 | struct kprobe_insn_page *kip; |
| 123 | struct hlist_node *pos; | 124 | struct hlist_node *pos; |
| @@ -152,20 +153,42 @@ void free_insn_slot(kprobe_opcode_t *slot) | |||
| 152 | } | 153 | } |
| 153 | 154 | ||
| 154 | /* Locks kprobe: irqs must be disabled */ | 155 | /* Locks kprobe: irqs must be disabled */ |
| 155 | void lock_kprobes(void) | 156 | void __kprobes lock_kprobes(void) |
| 156 | { | 157 | { |
| 158 | unsigned long flags = 0; | ||
| 159 | |||
| 160 | /* Avoiding local interrupts to happen right after we take the kprobe_lock | ||
| 161 | * and before we get a chance to update kprobe_cpu, this to prevent | ||
| 162 | * deadlock when we have a kprobe on ISR routine and a kprobe on task | ||
| 163 | * routine | ||
| 164 | */ | ||
| 165 | local_irq_save(flags); | ||
| 166 | |||
| 157 | spin_lock(&kprobe_lock); | 167 | spin_lock(&kprobe_lock); |
| 158 | kprobe_cpu = smp_processor_id(); | 168 | kprobe_cpu = smp_processor_id(); |
| 169 | |||
| 170 | local_irq_restore(flags); | ||
| 159 | } | 171 | } |
| 160 | 172 | ||
| 161 | void unlock_kprobes(void) | 173 | void __kprobes unlock_kprobes(void) |
| 162 | { | 174 | { |
| 175 | unsigned long flags = 0; | ||
| 176 | |||
| 177 | /* Avoiding local interrupts to happen right after we update | ||
| 178 | * kprobe_cpu and before we get a a chance to release kprobe_lock, | ||
| 179 | * this to prevent deadlock when we have a kprobe on ISR routine and | ||
| 180 | * a kprobe on task routine | ||
| 181 | */ | ||
| 182 | local_irq_save(flags); | ||
| 183 | |||
| 163 | kprobe_cpu = NR_CPUS; | 184 | kprobe_cpu = NR_CPUS; |
| 164 | spin_unlock(&kprobe_lock); | 185 | spin_unlock(&kprobe_lock); |
| 186 | |||
| 187 | local_irq_restore(flags); | ||
| 165 | } | 188 | } |
| 166 | 189 | ||
| 167 | /* You have to be holding the kprobe_lock */ | 190 | /* You have to be holding the kprobe_lock */ |
| 168 | struct kprobe *get_kprobe(void *addr) | 191 | struct kprobe __kprobes *get_kprobe(void *addr) |
| 169 | { | 192 | { |
| 170 | struct hlist_head *head; | 193 | struct hlist_head *head; |
| 171 | struct hlist_node *node; | 194 | struct hlist_node *node; |
| @@ -183,7 +206,7 @@ struct kprobe *get_kprobe(void *addr) | |||
| 183 | * Aggregate handlers for multiple kprobes support - these handlers | 206 | * Aggregate handlers for multiple kprobes support - these handlers |
| 184 | * take care of invoking the individual kprobe handlers on p->list | 207 | * take care of invoking the individual kprobe handlers on p->list |
| 185 | */ | 208 | */ |
| 186 | static int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs) | 209 | static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs) |
| 187 | { | 210 | { |
| 188 | struct kprobe *kp; | 211 | struct kprobe *kp; |
| 189 | 212 | ||
| @@ -198,8 +221,8 @@ static int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
| 198 | return 0; | 221 | return 0; |
| 199 | } | 222 | } |
| 200 | 223 | ||
| 201 | static void aggr_post_handler(struct kprobe *p, struct pt_regs *regs, | 224 | static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs, |
| 202 | unsigned long flags) | 225 | unsigned long flags) |
| 203 | { | 226 | { |
| 204 | struct kprobe *kp; | 227 | struct kprobe *kp; |
| 205 | 228 | ||
| @@ -213,8 +236,8 @@ static void aggr_post_handler(struct kprobe *p, struct pt_regs *regs, | |||
| 213 | return; | 236 | return; |
| 214 | } | 237 | } |
| 215 | 238 | ||
| 216 | static int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, | 239 | static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, |
| 217 | int trapnr) | 240 | int trapnr) |
| 218 | { | 241 | { |
| 219 | /* | 242 | /* |
| 220 | * if we faulted "during" the execution of a user specified | 243 | * if we faulted "during" the execution of a user specified |
| @@ -227,7 +250,7 @@ static int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, | |||
| 227 | return 0; | 250 | return 0; |
| 228 | } | 251 | } |
| 229 | 252 | ||
| 230 | static int aggr_break_handler(struct kprobe *p, struct pt_regs *regs) | 253 | static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs) |
| 231 | { | 254 | { |
| 232 | struct kprobe *kp = curr_kprobe; | 255 | struct kprobe *kp = curr_kprobe; |
| 233 | if (curr_kprobe && kp->break_handler) { | 256 | if (curr_kprobe && kp->break_handler) { |
| @@ -240,7 +263,7 @@ static int aggr_break_handler(struct kprobe *p, struct pt_regs *regs) | |||
| 240 | return 0; | 263 | return 0; |
| 241 | } | 264 | } |
| 242 | 265 | ||
| 243 | struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp) | 266 | struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp) |
| 244 | { | 267 | { |
| 245 | struct hlist_node *node; | 268 | struct hlist_node *node; |
| 246 | struct kretprobe_instance *ri; | 269 | struct kretprobe_instance *ri; |
| @@ -249,7 +272,8 @@ struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp) | |||
| 249 | return NULL; | 272 | return NULL; |
| 250 | } | 273 | } |
| 251 | 274 | ||
| 252 | static struct kretprobe_instance *get_used_rp_inst(struct kretprobe *rp) | 275 | static struct kretprobe_instance __kprobes *get_used_rp_inst(struct kretprobe |
| 276 | *rp) | ||
| 253 | { | 277 | { |
| 254 | struct hlist_node *node; | 278 | struct hlist_node *node; |
| 255 | struct kretprobe_instance *ri; | 279 | struct kretprobe_instance *ri; |
| @@ -258,7 +282,7 @@ static struct kretprobe_instance *get_used_rp_inst(struct kretprobe *rp) | |||
| 258 | return NULL; | 282 | return NULL; |
| 259 | } | 283 | } |
| 260 | 284 | ||
| 261 | void add_rp_inst(struct kretprobe_instance *ri) | 285 | void __kprobes add_rp_inst(struct kretprobe_instance *ri) |
| 262 | { | 286 | { |
| 263 | /* | 287 | /* |
| 264 | * Remove rp inst off the free list - | 288 | * Remove rp inst off the free list - |
| @@ -276,7 +300,7 @@ void add_rp_inst(struct kretprobe_instance *ri) | |||
| 276 | hlist_add_head(&ri->uflist, &ri->rp->used_instances); | 300 | hlist_add_head(&ri->uflist, &ri->rp->used_instances); |
| 277 | } | 301 | } |
| 278 | 302 | ||
| 279 | void recycle_rp_inst(struct kretprobe_instance *ri) | 303 | void __kprobes recycle_rp_inst(struct kretprobe_instance *ri) |
| 280 | { | 304 | { |
| 281 | /* remove rp inst off the rprobe_inst_table */ | 305 | /* remove rp inst off the rprobe_inst_table */ |
| 282 | hlist_del(&ri->hlist); | 306 | hlist_del(&ri->hlist); |
| @@ -291,7 +315,7 @@ void recycle_rp_inst(struct kretprobe_instance *ri) | |||
| 291 | kfree(ri); | 315 | kfree(ri); |
| 292 | } | 316 | } |
| 293 | 317 | ||
| 294 | struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk) | 318 | struct hlist_head __kprobes *kretprobe_inst_table_head(struct task_struct *tsk) |
| 295 | { | 319 | { |
| 296 | return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)]; | 320 | return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)]; |
| 297 | } | 321 | } |
| @@ -302,7 +326,7 @@ struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk) | |||
| 302 | * instances associated with this task. These left over instances represent | 326 | * instances associated with this task. These left over instances represent |
| 303 | * probed functions that have been called but will never return. | 327 | * probed functions that have been called but will never return. |
| 304 | */ | 328 | */ |
| 305 | void kprobe_flush_task(struct task_struct *tk) | 329 | void __kprobes kprobe_flush_task(struct task_struct *tk) |
| 306 | { | 330 | { |
| 307 | struct kretprobe_instance *ri; | 331 | struct kretprobe_instance *ri; |
| 308 | struct hlist_head *head; | 332 | struct hlist_head *head; |
| @@ -322,7 +346,8 @@ void kprobe_flush_task(struct task_struct *tk) | |||
| 322 | * This kprobe pre_handler is registered with every kretprobe. When probe | 346 | * This kprobe pre_handler is registered with every kretprobe. When probe |
| 323 | * hits it will set up the return probe. | 347 | * hits it will set up the return probe. |
| 324 | */ | 348 | */ |
| 325 | static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs) | 349 | static int __kprobes pre_handler_kretprobe(struct kprobe *p, |
| 350 | struct pt_regs *regs) | ||
| 326 | { | 351 | { |
| 327 | struct kretprobe *rp = container_of(p, struct kretprobe, kp); | 352 | struct kretprobe *rp = container_of(p, struct kretprobe, kp); |
| 328 | 353 | ||
| @@ -353,7 +378,7 @@ static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p) | |||
| 353 | * Add the new probe to old_p->list. Fail if this is the | 378 | * Add the new probe to old_p->list. Fail if this is the |
| 354 | * second jprobe at the address - two jprobes can't coexist | 379 | * second jprobe at the address - two jprobes can't coexist |
| 355 | */ | 380 | */ |
| 356 | static int add_new_kprobe(struct kprobe *old_p, struct kprobe *p) | 381 | static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p) |
| 357 | { | 382 | { |
| 358 | struct kprobe *kp; | 383 | struct kprobe *kp; |
| 359 | 384 | ||
| @@ -395,7 +420,8 @@ static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p) | |||
| 395 | * the intricacies | 420 | * the intricacies |
| 396 | * TODO: Move kcalloc outside the spinlock | 421 | * TODO: Move kcalloc outside the spinlock |
| 397 | */ | 422 | */ |
| 398 | static int register_aggr_kprobe(struct kprobe *old_p, struct kprobe *p) | 423 | static int __kprobes register_aggr_kprobe(struct kprobe *old_p, |
| 424 | struct kprobe *p) | ||
| 399 | { | 425 | { |
| 400 | int ret = 0; | 426 | int ret = 0; |
| 401 | struct kprobe *ap; | 427 | struct kprobe *ap; |
| @@ -434,15 +460,25 @@ static inline void cleanup_aggr_kprobe(struct kprobe *old_p, | |||
| 434 | spin_unlock_irqrestore(&kprobe_lock, flags); | 460 | spin_unlock_irqrestore(&kprobe_lock, flags); |
| 435 | } | 461 | } |
| 436 | 462 | ||
| 437 | int register_kprobe(struct kprobe *p) | 463 | static int __kprobes in_kprobes_functions(unsigned long addr) |
| 464 | { | ||
| 465 | if (addr >= (unsigned long)__kprobes_text_start | ||
| 466 | && addr < (unsigned long)__kprobes_text_end) | ||
| 467 | return -EINVAL; | ||
| 468 | return 0; | ||
| 469 | } | ||
| 470 | |||
| 471 | int __kprobes register_kprobe(struct kprobe *p) | ||
| 438 | { | 472 | { |
| 439 | int ret = 0; | 473 | int ret = 0; |
| 440 | unsigned long flags = 0; | 474 | unsigned long flags = 0; |
| 441 | struct kprobe *old_p; | 475 | struct kprobe *old_p; |
| 442 | 476 | ||
| 443 | if ((ret = arch_prepare_kprobe(p)) != 0) { | 477 | if ((ret = in_kprobes_functions((unsigned long) p->addr)) != 0) |
| 478 | return ret; | ||
| 479 | if ((ret = arch_prepare_kprobe(p)) != 0) | ||
| 444 | goto rm_kprobe; | 480 | goto rm_kprobe; |
| 445 | } | 481 | |
| 446 | spin_lock_irqsave(&kprobe_lock, flags); | 482 | spin_lock_irqsave(&kprobe_lock, flags); |
| 447 | old_p = get_kprobe(p->addr); | 483 | old_p = get_kprobe(p->addr); |
| 448 | p->nmissed = 0; | 484 | p->nmissed = 0; |
| @@ -466,7 +502,7 @@ rm_kprobe: | |||
| 466 | return ret; | 502 | return ret; |
| 467 | } | 503 | } |
| 468 | 504 | ||
| 469 | void unregister_kprobe(struct kprobe *p) | 505 | void __kprobes unregister_kprobe(struct kprobe *p) |
| 470 | { | 506 | { |
| 471 | unsigned long flags; | 507 | unsigned long flags; |
| 472 | struct kprobe *old_p; | 508 | struct kprobe *old_p; |
| @@ -487,7 +523,7 @@ static struct notifier_block kprobe_exceptions_nb = { | |||
| 487 | .priority = 0x7fffffff /* we need to notified first */ | 523 | .priority = 0x7fffffff /* we need to notified first */ |
| 488 | }; | 524 | }; |
| 489 | 525 | ||
| 490 | int register_jprobe(struct jprobe *jp) | 526 | int __kprobes register_jprobe(struct jprobe *jp) |
| 491 | { | 527 | { |
| 492 | /* Todo: Verify probepoint is a function entry point */ | 528 | /* Todo: Verify probepoint is a function entry point */ |
| 493 | jp->kp.pre_handler = setjmp_pre_handler; | 529 | jp->kp.pre_handler = setjmp_pre_handler; |
| @@ -496,14 +532,14 @@ int register_jprobe(struct jprobe *jp) | |||
| 496 | return register_kprobe(&jp->kp); | 532 | return register_kprobe(&jp->kp); |
| 497 | } | 533 | } |
| 498 | 534 | ||
| 499 | void unregister_jprobe(struct jprobe *jp) | 535 | void __kprobes unregister_jprobe(struct jprobe *jp) |
| 500 | { | 536 | { |
| 501 | unregister_kprobe(&jp->kp); | 537 | unregister_kprobe(&jp->kp); |
| 502 | } | 538 | } |
| 503 | 539 | ||
| 504 | #ifdef ARCH_SUPPORTS_KRETPROBES | 540 | #ifdef ARCH_SUPPORTS_KRETPROBES |
| 505 | 541 | ||
| 506 | int register_kretprobe(struct kretprobe *rp) | 542 | int __kprobes register_kretprobe(struct kretprobe *rp) |
| 507 | { | 543 | { |
| 508 | int ret = 0; | 544 | int ret = 0; |
| 509 | struct kretprobe_instance *inst; | 545 | struct kretprobe_instance *inst; |
| @@ -540,14 +576,14 @@ int register_kretprobe(struct kretprobe *rp) | |||
| 540 | 576 | ||
| 541 | #else /* ARCH_SUPPORTS_KRETPROBES */ | 577 | #else /* ARCH_SUPPORTS_KRETPROBES */ |
| 542 | 578 | ||
| 543 | int register_kretprobe(struct kretprobe *rp) | 579 | int __kprobes register_kretprobe(struct kretprobe *rp) |
| 544 | { | 580 | { |
| 545 | return -ENOSYS; | 581 | return -ENOSYS; |
| 546 | } | 582 | } |
| 547 | 583 | ||
| 548 | #endif /* ARCH_SUPPORTS_KRETPROBES */ | 584 | #endif /* ARCH_SUPPORTS_KRETPROBES */ |
| 549 | 585 | ||
| 550 | void unregister_kretprobe(struct kretprobe *rp) | 586 | void __kprobes unregister_kretprobe(struct kretprobe *rp) |
| 551 | { | 587 | { |
| 552 | unsigned long flags; | 588 | unsigned long flags; |
| 553 | struct kretprobe_instance *ri; | 589 | struct kretprobe_instance *ri; |
