Revert "ARM: dts: aspeed: Add USB2.0 device controller node"
[platform/kernel/linux-starfive.git] / mm / kfence / core.c
index 11a9547..4e7cd4c 100644 (file)
@@ -21,6 +21,8 @@
 #include <linux/log2.h>
 #include <linux/memblock.h>
 #include <linux/moduleparam.h>
+#include <linux/notifier.h>
+#include <linux/panic_notifier.h>
 #include <linux/random.h>
 #include <linux/rcupdate.h>
 #include <linux/sched/clock.h>
@@ -67,8 +69,11 @@ static int param_set_sample_interval(const char *val, const struct kernel_param
        if (ret < 0)
                return ret;
 
-       if (!num) /* Using 0 to indicate KFENCE is disabled. */
+       /* Using 0 to indicate KFENCE is disabled. */
+       if (!num && READ_ONCE(kfence_enabled)) {
+               pr_info("disabled\n");
                WRITE_ONCE(kfence_enabled, false);
+       }
 
        *((unsigned long *)kp->arg) = num;
 
@@ -99,6 +104,10 @@ module_param_named(skip_covered_thresh, kfence_skip_covered_thresh, ulong, 0644)
 static bool kfence_deferrable __read_mostly = IS_ENABLED(CONFIG_KFENCE_DEFERRABLE);
 module_param_named(deferrable, kfence_deferrable, bool, 0444);
 
+/* If true, check all canary bytes on panic. */
+static bool kfence_check_on_panic __read_mostly;
+module_param_named(check_on_panic, kfence_check_on_panic, bool, 0444);
+
 /* The pool of pages used for guard pages and objects. */
 char *__kfence_pool __read_mostly;
 EXPORT_SYMBOL(__kfence_pool); /* Export for test modules. */
@@ -737,6 +746,31 @@ static int __init kfence_debugfs_init(void)
 
 late_initcall(kfence_debugfs_init);
 
+/* === Panic Notifier ====================================================== */
+
+static void kfence_check_all_canary(void)
+{
+       int i;
+
+       for (i = 0; i < CONFIG_KFENCE_NUM_OBJECTS; i++) {
+               struct kfence_metadata *meta = &kfence_metadata[i];
+
+               if (meta->state == KFENCE_OBJECT_ALLOCATED)
+                       for_each_canary(meta, check_canary_byte);
+       }
+}
+
+static int kfence_check_canary_callback(struct notifier_block *nb,
+                                       unsigned long reason, void *arg)
+{
+       kfence_check_all_canary();
+       return NOTIFY_OK;
+}
+
+static struct notifier_block kfence_check_canary_notifier = {
+       .notifier_call = kfence_check_canary_callback,
+};
+
 /* === Allocation Gate Timer ================================================ */
 
 static struct delayed_work kfence_timer;
@@ -814,6 +848,9 @@ static void kfence_init_enable(void)
        else
                INIT_DELAYED_WORK(&kfence_timer, toggle_allocation_gate);
 
+       if (kfence_check_on_panic)
+               atomic_notifier_chain_register(&panic_notifier_list, &kfence_check_canary_notifier);
+
        WRITE_ONCE(kfence_enabled, true);
        queue_delayed_work(system_unbound_wq, &kfence_timer, 0);
 
@@ -874,6 +911,7 @@ static int kfence_enable_late(void)
 
        WRITE_ONCE(kfence_enabled, true);
        queue_delayed_work(system_unbound_wq, &kfence_timer, 0);
+       pr_info("re-enabled\n");
        return 0;
 }