X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=kernel%2Fkprobes.c;h=ec1748679b45105615776df20bec18dd14cc02f7;hp=e5d84644823b4094a4e6c629985daddd753bdd19;hb=4cecd7e369e1b252db1d64451462221b362eed1c;hpb=3cdc3acc62527ab9544c2820b5e5da482a105240 diff --git a/kernel/kprobes.c b/kernel/kprobes.c index e5d84644823b..ec1748679b45 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -53,6 +53,9 @@ #include #include #include +#ifdef CONFIG_RETPOLINE +#include +#endif #define KPROBE_HASH_BITS 6 #define KPROBE_TABLE_SIZE (1 << KPROBE_HASH_BITS) @@ -99,6 +102,11 @@ static struct kprobe_blackpoint kprobe_blacklist[] = { {"irq_entries_start",}, {"common_interrupt",}, {"mcount",}, /* mcount can be called from everywhere */ +#ifdef CONFIG_RETPOLINE + {"__indirect_thunk_start", + /* Linker scripts can't set symbol sizes */ + .range = (size_t)__indirect_thunk_size}, +#endif {NULL} /* Terminator */ }; @@ -598,7 +606,7 @@ static __kprobes void kprobe_optimizer(struct work_struct *work) } /* Wait for completing optimization and unoptimization */ -static __kprobes void wait_for_kprobe_optimizer(void) +__kprobes void wait_for_kprobe_optimizer(void) { if (delayed_work_pending(&optimizing_work)) wait_for_completion(&optimizer_comp); @@ -1077,6 +1085,7 @@ void __kprobes kprobe_flush_task(struct task_struct *tk) /* Early boot. kretprobe_table_locks not yet initialized. */ return; + INIT_HLIST_HEAD(&empty_rp); hash = hash_ptr(tk, KPROBE_HASH_BITS); head = &kretprobe_inst_table[hash]; kretprobe_table_lock(hash, &flags); @@ -1085,7 +1094,6 @@ void __kprobes kprobe_flush_task(struct task_struct *tk) recycle_rp_inst(ri, &empty_rp); } kretprobe_table_unlock(hash, &flags); - INIT_HLIST_HEAD(&empty_rp); hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { hlist_del(&ri->hlist); kfree(ri); @@ -1334,8 +1342,10 @@ int __kprobes register_kprobe(struct kprobe *p) if (!kernel_text_address((unsigned long) p->addr) || in_kprobes_functions((unsigned long) p->addr) || ftrace_text_reserved(p->addr, p->addr) || - jump_label_text_reserved(p->addr, p->addr)) - goto fail_with_jump_label; + jump_label_text_reserved(p->addr, p->addr)) { + ret = -EINVAL; + goto cannot_probe; + } /* User can pass only KPROBE_FLAG_DISABLED to register_kprobe */ p->flags &= KPROBE_FLAG_DISABLED; @@ -1352,7 +1362,7 @@ int __kprobes register_kprobe(struct kprobe *p) * its code to prohibit unexpected unloading. */ if (unlikely(!try_module_get(probed_mod))) - goto fail_with_jump_label; + goto cannot_probe; /* * If the module freed .init.text, we couldn't insert @@ -1361,7 +1371,7 @@ int __kprobes register_kprobe(struct kprobe *p) if (within_module_init((unsigned long)p->addr, probed_mod) && probed_mod->state != MODULE_STATE_COMING) { module_put(probed_mod); - goto fail_with_jump_label; + goto cannot_probe; } /* ret will be updated by following code */ } @@ -1409,7 +1419,7 @@ out: return ret; -fail_with_jump_label: +cannot_probe: preempt_enable(); jump_label_unlock(); return ret; @@ -1673,8 +1683,12 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p, ri->rp = rp; ri->task = current; - if (rp->entry_handler && rp->entry_handler(ri, regs)) + if (rp->entry_handler && rp->entry_handler(ri, regs)) { + raw_spin_lock_irqsave(&rp->lock, flags); + hlist_add_head(&ri->hlist, &rp->free_instances); + raw_spin_unlock_irqrestore(&rp->lock, flags); return 0; + } arch_prepare_kretprobe(ri, regs); @@ -1980,7 +1994,7 @@ static int __init init_kprobes(void) &size, &offset, &modname, namebuf); if (!symbol_name) kb->range = 0; - else + else if (size) kb->range = size; }