]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - kernel/kprobes.c
filemap: check compound_head(page)->mapping in pagecache_get_page()
[linux.git] / kernel / kprobes.c
index d9770a5393c89925d2fa3f391dfb341a34a70409..53534aa258a60ec3ba7dad1cf3551e26d8f19700 100644 (file)
@@ -961,9 +961,16 @@ static struct kprobe *alloc_aggr_kprobe(struct kprobe *p)
 
 #ifdef CONFIG_KPROBES_ON_FTRACE
 static struct ftrace_ops kprobe_ftrace_ops __read_mostly = {
+       .func = kprobe_ftrace_handler,
+       .flags = FTRACE_OPS_FL_SAVE_REGS,
+};
+
+static struct ftrace_ops kprobe_ipmodify_ops __read_mostly = {
        .func = kprobe_ftrace_handler,
        .flags = FTRACE_OPS_FL_SAVE_REGS | FTRACE_OPS_FL_IPMODIFY,
 };
+
+static int kprobe_ipmodify_enabled;
 static int kprobe_ftrace_enabled;
 
 /* Must ensure p->addr is really on ftrace */
@@ -976,58 +983,75 @@ static int prepare_kprobe(struct kprobe *p)
 }
 
 /* Caller must lock kprobe_mutex */
-static int arm_kprobe_ftrace(struct kprobe *p)
+static int __arm_kprobe_ftrace(struct kprobe *p, struct ftrace_ops *ops,
+                              int *cnt)
 {
        int ret = 0;
 
-       ret = ftrace_set_filter_ip(&kprobe_ftrace_ops,
-                                  (unsigned long)p->addr, 0, 0);
+       ret = ftrace_set_filter_ip(ops, (unsigned long)p->addr, 0, 0);
        if (ret) {
                pr_debug("Failed to arm kprobe-ftrace at %pS (%d)\n",
                         p->addr, ret);
                return ret;
        }
 
-       if (kprobe_ftrace_enabled == 0) {
-               ret = register_ftrace_function(&kprobe_ftrace_ops);
+       if (*cnt == 0) {
+               ret = register_ftrace_function(ops);
                if (ret) {
                        pr_debug("Failed to init kprobe-ftrace (%d)\n", ret);
                        goto err_ftrace;
                }
        }
 
-       kprobe_ftrace_enabled++;
+       (*cnt)++;
        return ret;
 
 err_ftrace:
        /*
-        * Note: Since kprobe_ftrace_ops has IPMODIFY set, and ftrace requires a
-        * non-empty filter_hash for IPMODIFY ops, we're safe from an accidental
-        * empty filter_hash which would undesirably trace all functions.
+        * At this point, sinec ops is not registered, we should be sefe from
+        * registering empty filter.
         */
-       ftrace_set_filter_ip(&kprobe_ftrace_ops, (unsigned long)p->addr, 1, 0);
+       ftrace_set_filter_ip(ops, (unsigned long)p->addr, 1, 0);
        return ret;
 }
 
+static int arm_kprobe_ftrace(struct kprobe *p)
+{
+       bool ipmodify = (p->post_handler != NULL);
+
+       return __arm_kprobe_ftrace(p,
+               ipmodify ? &kprobe_ipmodify_ops : &kprobe_ftrace_ops,
+               ipmodify ? &kprobe_ipmodify_enabled : &kprobe_ftrace_enabled);
+}
+
 /* Caller must lock kprobe_mutex */
-static int disarm_kprobe_ftrace(struct kprobe *p)
+static int __disarm_kprobe_ftrace(struct kprobe *p, struct ftrace_ops *ops,
+                                 int *cnt)
 {
        int ret = 0;
 
-       if (kprobe_ftrace_enabled == 1) {
-               ret = unregister_ftrace_function(&kprobe_ftrace_ops);
+       if (*cnt == 1) {
+               ret = unregister_ftrace_function(ops);
                if (WARN(ret < 0, "Failed to unregister kprobe-ftrace (%d)\n", ret))
                        return ret;
        }
 
-       kprobe_ftrace_enabled--;
+       (*cnt)--;
 
-       ret = ftrace_set_filter_ip(&kprobe_ftrace_ops,
-                          (unsigned long)p->addr, 1, 0);
+       ret = ftrace_set_filter_ip(ops, (unsigned long)p->addr, 1, 0);
        WARN_ONCE(ret < 0, "Failed to disarm kprobe-ftrace at %pS (%d)\n",
                  p->addr, ret);
        return ret;
 }
+
+static int disarm_kprobe_ftrace(struct kprobe *p)
+{
+       bool ipmodify = (p->post_handler != NULL);
+
+       return __disarm_kprobe_ftrace(p,
+               ipmodify ? &kprobe_ipmodify_ops : &kprobe_ftrace_ops,
+               ipmodify ? &kprobe_ipmodify_enabled : &kprobe_ftrace_enabled);
+}
 #else  /* !CONFIG_KPROBES_ON_FTRACE */
 #define prepare_kprobe(p)      arch_prepare_kprobe(p)
 #define arm_kprobe_ftrace(p)   (-ENODEV)
@@ -1514,7 +1538,8 @@ static int check_kprobe_address_safe(struct kprobe *p,
        /* Ensure it is not in reserved area nor out of text */
        if (!kernel_text_address((unsigned long) p->addr) ||
            within_kprobe_blacklist((unsigned long) p->addr) ||
-           jump_label_text_reserved(p->addr, p->addr)) {
+           jump_label_text_reserved(p->addr, p->addr) ||
+           find_bug((unsigned long)p->addr)) {
                ret = -EINVAL;
                goto out;
        }
@@ -1906,7 +1931,7 @@ int register_kretprobe(struct kretprobe *rp)
 
        /* Pre-allocate memory for max kretprobe instances */
        if (rp->maxactive <= 0) {
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
                rp->maxactive = max_t(unsigned int, 10, 2*num_possible_cpus());
 #else
                rp->maxactive = num_possible_cpus();