]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - kernel/kprobes.c
kprobes: Verify jprobe entry point
[net-next-2.6.git] / kernel / kprobes.c
index 0ed46f3e51e9812e036ed618a1bc5c12e9328de9..1b0dbe0670770f2fece89c78335752ed7619b397 100644 (file)
@@ -1339,18 +1339,19 @@ int __kprobes register_jprobes(struct jprobe **jps, int num)
        if (num <= 0)
                return -EINVAL;
        for (i = 0; i < num; i++) {
-               unsigned long addr;
+               unsigned long addr, offset;
                jp = jps[i];
                addr = arch_deref_entry_point(jp->entry);
 
-               if (!kernel_text_address(addr))
-                       ret = -EINVAL;
-               else {
-                       /* Todo: Verify probepoint is a function entry point */
+               /* Verify probepoint is a function entry point */
+               if (kallsyms_lookup_size_offset(addr, NULL, &offset) &&
+                   offset == 0) {
                        jp->kp.pre_handler = setjmp_pre_handler;
                        jp->kp.break_handler = longjmp_break_handler;
                        ret = register_kprobe(&jp->kp);
-               }
+               } else
+                       ret = -EINVAL;
+
                if (ret < 0) {
                        if (i > 0)
                                unregister_jprobes(jps, i);
@@ -1588,6 +1589,72 @@ static void __kprobes kill_kprobe(struct kprobe *p)
        arch_remove_kprobe(p);
 }
 
+/* Disable one kprobe */
+int __kprobes disable_kprobe(struct kprobe *kp)
+{
+       int ret = 0;
+       struct kprobe *p;
+
+       mutex_lock(&kprobe_mutex);
+
+       /* Check whether specified probe is valid. */
+       p = __get_valid_kprobe(kp);
+       if (unlikely(p == NULL)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       /* If the probe is already disabled (or gone), just return */
+       if (kprobe_disabled(kp))
+               goto out;
+
+       kp->flags |= KPROBE_FLAG_DISABLED;
+       if (p != kp)
+               /* When kp != p, p is always enabled. */
+               try_to_disable_aggr_kprobe(p);
+
+       if (!kprobes_all_disarmed && kprobe_disabled(p))
+               disarm_kprobe(p);
+out:
+       mutex_unlock(&kprobe_mutex);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(disable_kprobe);
+
+/* Enable one kprobe */
+int __kprobes enable_kprobe(struct kprobe *kp)
+{
+       int ret = 0;
+       struct kprobe *p;
+
+       mutex_lock(&kprobe_mutex);
+
+       /* Check whether specified probe is valid. */
+       p = __get_valid_kprobe(kp);
+       if (unlikely(p == NULL)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (kprobe_gone(kp)) {
+               /* This kprobe has gone, we couldn't enable it. */
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (p != kp)
+               kp->flags &= ~KPROBE_FLAG_DISABLED;
+
+       if (!kprobes_all_disarmed && kprobe_disabled(p)) {
+               p->flags &= ~KPROBE_FLAG_DISABLED;
+               arm_kprobe(p);
+       }
+out:
+       mutex_unlock(&kprobe_mutex);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(enable_kprobe);
+
 void __kprobes dump_kprobe(struct kprobe *kp)
 {
        printk(KERN_WARNING "Dumping kprobe:\n");
@@ -1805,72 +1872,6 @@ static const struct file_operations debugfs_kprobes_operations = {
        .release        = seq_release,
 };
 
-/* Disable one kprobe */
-int __kprobes disable_kprobe(struct kprobe *kp)
-{
-       int ret = 0;
-       struct kprobe *p;
-
-       mutex_lock(&kprobe_mutex);
-
-       /* Check whether specified probe is valid. */
-       p = __get_valid_kprobe(kp);
-       if (unlikely(p == NULL)) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       /* If the probe is already disabled (or gone), just return */
-       if (kprobe_disabled(kp))
-               goto out;
-
-       kp->flags |= KPROBE_FLAG_DISABLED;
-       if (p != kp)
-               /* When kp != p, p is always enabled. */
-               try_to_disable_aggr_kprobe(p);
-
-       if (!kprobes_all_disarmed && kprobe_disabled(p))
-               disarm_kprobe(p);
-out:
-       mutex_unlock(&kprobe_mutex);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(disable_kprobe);
-
-/* Enable one kprobe */
-int __kprobes enable_kprobe(struct kprobe *kp)
-{
-       int ret = 0;
-       struct kprobe *p;
-
-       mutex_lock(&kprobe_mutex);
-
-       /* Check whether specified probe is valid. */
-       p = __get_valid_kprobe(kp);
-       if (unlikely(p == NULL)) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       if (kprobe_gone(kp)) {
-               /* This kprobe has gone, we couldn't enable it. */
-               ret = -EINVAL;
-               goto out;
-       }
-
-       if (p != kp)
-               kp->flags &= ~KPROBE_FLAG_DISABLED;
-
-       if (!kprobes_all_disarmed && kprobe_disabled(p)) {
-               p->flags &= ~KPROBE_FLAG_DISABLED;
-               arm_kprobe(p);
-       }
-out:
-       mutex_unlock(&kprobe_mutex);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(enable_kprobe);
-
 static void __kprobes arm_all_kprobes(void)
 {
        struct hlist_head *head;